Files
HiveGrid-Wireframes/hivegrid-cloud/docs/boilerplate-mapping/M37-plattform-admin.md
T

21 KiB
Raw Blame History

Boilerplate-Mapping: M37 — Plattform-Admin

Modul-ID: M37 (Detail-Spec) / Milestones M034–M041 (Block 1, Pflichtenheft 37.x) Name: Plattform-Admin (admin.hivegrid.de) Reuse-Level: medium

Verifiziert direkt gegen /Users/raffaelsheikh/Documents/GitHub/boilerplate (Schema, Routes, Services). Inventur-Dateien als Ausgangspunkt, alle Aussagen mit eigenem Grep/Read gegengeprueft.


Kernbefund (zuerst lesen)

Die Boilerplate enthaelt eine substanzielle, fertige Admin-Welt (eigene Admin-Subdomain-Routing-Schicht, Admin-Sidebar, Admin-Login inkl. SSO + MFA-Step-up, RBAC, tamper-evidenter Audit-Trail, Impersonation-Infrastruktur, Lead-Inbox, Support-Tickets, Subscription-/Metrics-/Dashboard-Routen). Damit sind Themenblöcke E, F, G(lese), H, I, L, M, O zu grossen Teilen aus Vorhandenem ableitbar.

ABER: Die zentrale Architektur-Prämisse von M37 wird vom Boilerplate-Modell verletzt. Spec Block A/B verlangt eine eigene, parallele User-Klasse AdminUser mit eigenem password_hash, totp_secret, eigener AdminSession, eigener AdminRole/AdminPermission-RBAC und eigener AdminAuditLog-Tabelle. Im Boilerplate ist AdminUser jedoch kein eigenständiges Identity-Modell, sondern eine 1:1-Erweiterung von User:

// prisma/schema/accounts.prisma:112
model AdminUser {
  userId String @id @unique
  user   User   @relation(fields: [userId], references: [id], onDelete: Cascade)
  ssoProvider String?  ssoSubjectId String?  ssoGroups String[]  lastSsoLoginAt DateTime?
}

D.h. Admin-Auth, Passwort, 2FA und Rollen laufen heute über dasselbe User-/UserRole-/Permission-Fundament wie Tenant-User (Admin-Status = User hat AdminUser-Zeile). Das ist exakt der „Generalschlüssel zwischen den Welten", den Spec Block A.2/A.3 und Milestone M034 (37.1) verbieten.

Konsequenz für die Planung: Vor jeder Übernahme muss eine Architektur-Entscheidung fallen:

  • (a) Spec-treu (empfohlen lt. Spec): neue, vollständig getrennte AdminUser-Identität + AdminSession + AdminRole/AdminPermission/AdminAuditLog neu bauen. Boilerplate-Admin-Auth dient dann nur als Vorlage (Login-Form, MFA-Flow, Rate-Limit, Session-Cookie-Policy), nicht 1:1.
  • (b) Boilerplate-treu: das bestehende User+AdminUser-Extension-Modell behalten und Spec Block A/B abschwächen (Change-Request, da es Pflichtenheft 37.1 widerspricht).

Dieser Punkt ist der Haupt-Grund, warum Reuse medium und nicht high ist.


Übernehmbar aus Boilerplate

Boilerplate-Pfad Was Wie nutzbar
apps/web/app/routes/admin.tsx + apps/web/app/routes/admin/ (Tree) Komplette Admin-Route-Welt unter eigener Surface (accounts, users, subscriptions, roles-and-permissions, audit-trails, metrics, feature-flags, marketing-leads, help-desk, settings, events) inkl. host-aware Subdomain-Routing-Tests (admin.host-aware.test.ts) als-vorlage (Routen-Skelett + Subdomain-Trennung direkt; Inhalte HiveGrid-fachlich füllen)
apps/web/app/application/sidebar/AdminSidebar.tsx + SidebarItem.ts + SidebarGroupDto.ts Statische, permission-getaggte Admin-Sidebar in Segmenten (Manage/Build/Market/Settings), data-ui-id-IDs, adminPath()-host-aware anpassen (Sidebar-Hauptpunkte aus Block E übernehmen; HiveGrid nutzt eigene packages/ui-hivegrid/src/app-shell/sidebar.config.ts — INTEGRATION-CONTRACTS §2)
packages/url/src/canonical.ts (adminPath/adminUrl) + packages/config/src/routing.ts + packages/config/src/session-cookie.ts Host-aware Admin-URL-Builder, Domain-Routing, domain-/pfad-gelockte Session-Cookie-Policy 1:1 (Cookie-Trennung admin. vs app. = Block A.3, M034)
apps/web/app/routes/auth.admin.login.tsx, auth.admin.callback.tsx, auth.admin.logout.tsx Eigener Admin-Login-/Logout-Flow (heute via Authentik-OIDC) als-vorlage (Flow-Gerüst; HiveGrid braucht Email+Passwort+TOTP statt OIDC — Block C; Magic-Link für Admin verbieten)
apps/web/app/services/auth/admin-mfa-gate.server.ts (requireAdminMfaForAction, SENSITIVE_ADMIN_ACTIONS) + apps/web/app/utils/auth/mfa/* (enforcement.server, step-up.server) MFA-Step-up-Gate für sensible Admin-Aktionen — Taxonomie enthält bereits impersonation.start, tenant.delete, permission.grant, audit.export, data.export anpassen (deckt Block C 2FA-Pflicht + Block Q Reason-Gates fachlich; auf neue AdminUser-Identität umhängen)
apps/api/src/auth/login-rate-limit.ts (createFixedWindowRateLimiter) + packages/shared-store (createFixedWindow/SlidingWindowRateLimiter) Login-Rate-Limit (IP + Account-Fingerprint, Redis) anpassen (Spec C: 5/15min Lock, Captcha ab 3., 10/24h → locked)
apps/web/app/utils/session.server.ts (Impersonation-State) + apps/web/app/utils/session.impersonation.test.ts Impersonation-Session-State (impersonatingFromUserId/StartedAt, Validierung) anpassen (Block G Impersonate; Spec: max 30 Min Cap + Reason-Pflicht ergänzen)
apps/web/app/components/impersonation-banner.tsx + apps/web/app/root.tsx (Wiring) + root.impersonation-banner.test.tsx Rotes Klartext-Impersonation-Banner in der App-Shell (i18n, „Acting as … from …", Exit) anpassen (Block G/M037: Banner-Text „Plattform-Support … Ticket #123" + Ticket-/Reason-Bezug)
prisma/schema/accounts.prisma:266 ImpersonationAudit + packages/db/src/impersonation-audit.server.ts Impersonation-Audit-Tabelle (actorUserId/targetUserId/tenantId/action/reason/requestPath/metadata, SetNull) 1:1 (deckt M037 Audit-Spur inkl. Reason)
prisma/schema/core.prisma:55 AuditEvent + packages/db/src/audit-events.server.ts + packages/db/src/audit-hash.ts + packages/foundation/src/audit.ts (auditEvent, withAuditMiddleware) Tamper-evidenter, cross-tenant-fähiger Audit-Trail (Hash-Kette, tenantId?, actorType, action, targetType/Id, metadata, reiche Indizes) 1:1 als AdminAuditLog-Ersatz — tenantId=null = plattform-/operator-weit deckt Block B AdminAuditLog fachlich vollständig ab; HiveGrid muss kein neues Audit-Schema bauen, nur action_type/target_kind-Vokabular definieren
apps/web/app/routes/admin/audit-trails.tsx + audit-export.tsx/.helpers.server.ts + packages/db/src/logs.server.ts (getAdminAuditLogList, serializeAdminAuditLogsCsv) Cross-Tenant-Audit-Liste mit Filter (Akteur/Action/Zeitraum) + CSV-Export, permission-gated (admin.auditTrails.view) anpassen (Block L fast vollständig; Volltext-Suche in summary_text + JSON-Export ergänzen)
packages/exports/src/audit-pdf.ts (serializeAuditEventsToPdf) Compliance-Audit-PDF (SOC2/HIPAA/GDPR-Evidence) 1:1 (Block L Compliance-Export)
prisma/schema/permissions.prisma (Role/Permission/RolePermission/UserRole/Group) + apps/web/app/routes/admin/accounts/roles-and-permissions.tsx + components/core/roles/* + packages/db/src/permissions-seed.server.ts Editierbares RBAC mit UI-Rollen-Editor + Permission-Seed als-vorlage (Block D Bundle-Modell; bei Architektur (a) als AdminRole/AdminPermission parallel neu, Struktur 1:1 übertragbar)
apps/web/app/utils/services/adminDashboardService.ts + packages/db/src/kpi.server.ts (getAdminTenantKpiCounts, getAdminActiveUserKpiCounts) + apps/web/app/utils/services/.server/subscriptionService.ts (getMrr) Admin-Dashboard-KPIs: Tenant-Count + Trend, MRR, aktive User anpassen (Block F: MRR/ARPU/Churn/Expansion + Health-Kacheln + Sales-Pipeline ergänzen)
apps/web/app/routes/admin/accounts/index.tsx + $id.tsx (Tenant) + users.tsx/users.test.tsx + blacklist.tsx + __ip-addresses/ Tenant-Liste/-Detail + User-Verwaltung + IP-Logs + Blacklist anpassen (Block G/H: Status-Wechsel mit Reason, Notes, Trial-Verlängerung, Bulk-Actions ergänzen)
apps/web/app/routes/admin/accounts/subscriptions.tsx + subscriptions/$id.tsx + subscriptions-revenue.tsx + prisma/schema/subscriptions.prisma (14 Modelle) + apps/web/app/utils/stripe.server.ts + packages/entitlements Vollständiger Stripe-Billing-Stack + Admin-Subscription-Routen + MRR anpassen (Block I: manueller Override, Force-Sync, Refund, Sonderpreis-Vermerk ergänzen)
prisma/schema/featureFlags.prisma (3 Modelle, append-only Audit) + packages/feature-flags (Engine v2, Targeting, Cache) + apps/web/app/routes/admin/feature-flags.tsx Feature-Flag-Engine + Admin-Verwaltung 1:1 (Block J = Verweis auf Modul 32; Admin-Routes liegen bereits unter admin/feature-flags)
prisma/schema/marketingLeads.prisma (Lead/LeadEvent/TenantAcquisition/MarketingIntegration, operator-scoped, kein tenantId) + apps/web/app/routes/admin/marketing-leads/index.tsx+$id.tsx + apps/web/app/utils/leads/* + packages/marketing-outbound Operator-scoped Lead-Inbox + Detail + Status-Pipeline + First-Touch-Attribution + Convert-to-Tenant (convertedToTenantId) + Activity-Timeline (LeadEvent) + Outbound-Adapter anpassen (Block M: deckt Lead-Inbox/Detail/Promote-to-Tenant/Activity-Stream sehr nah; fehlt: AdminDeal-Pipeline/Kanban, assigned_to, industry/company_size-Enums)
prisma/schema/helpDesk.prisma (Feedback, SupportTicket mit source/status/priority/inboundMessageId-Dedup) + apps/web/app/modules/helpDesk/* + apps/web/app/routes/admin/help-desk.tsx + components/FeedbackTable.tsx Support-Ticket-Aufnahme inkl. Inbound-Email-Dedup + PII-Redaction + Admin-Inbox anpassen (Block O: Konversation/Messages, Tags[], Assignee, Reply-Templates, Internal-Notes fehlen → erweitern)
apps/web/app/routes/admin/metrics/ (summary.tsx, logs.tsx, settings.tsx) + packages/metrics (prom-client, AI-Cost-Counter) + apps/worker/src/admin-server.ts/health-server.ts + infra/grafana (queue-health, business-kpi Dashboards) Metrics-Admin-Routen + Worker-Status/Health-Server + Grafana-Dashboards anpassen (Block K Health-Dashboard: Service-Status + Error-Rate als Vorlage; BullMQ-Queue-Steuerung-UI + KWP-Sync neu)
prisma/schema/queue.prisma (QueueFailedJob BullMQ-DLQ, ExportJob) + apps/worker/src/jobs/queue-failed-jobs* + packages/db/src/queue-failed-jobs.server.ts Failed-Job-Tracking (DLQ) anpassen (Block K Worker-Queues: Liste/Retry/Pause-UI darauf aufbauen)
packages/foundation/src/permissions.ts (withTenantScope/withPermission/requirePermission) + apps/web/app/utils/helpers/.server/PermissionsService.ts (verifyUserHasPermission) Permission-Gating + 404-statt-403 (Existenz-Versteckung) 1:1 (Querschnitt; Block D-Durchsetzung + AGENTS DoD C.17)
packages/foundation/src/notifications.ts (notify/bundleNotifications) + prisma/schema/notifications.prisma + prisma/schema/email.prisma (Campaign/OutboundEmail) Notifications + Outbound-Email/Kampagnen (für Bulk-Email an Tenant-Admins, AVV-Re-Akzeptanz-Mails) 1:1 / anpassen (Block G Bulk-Email, Block P AVV-Notification)
packages/exports (CSV/JSON/XLSX) + apps/worker/src/jobs/{export,dsgvo-export}.ts + prisma/schema/queue.prisma ExportJob DSGVO-/Daten-Export-Pipeline (Tenant-Daten-Export-Anstoss, Block G) 1:1
packages/foundation/src/errors.ts (CatalogError) + packages/view-models (VMState, ActionCallbacks, RegistryGate) + packages/i18n Klartext-Diagnostik, View-Model-Vertrag, i18n 1:1 (Querschnitt; Block Q Klartext-Hinweise, AGENTS DoD A/E)

Vorhandene Daten-Modelle (konkret, mit Pfad)

Modell Pfad M37-Bezug
AdminUser prisma/schema/accounts.prisma:112 nur Teilabdeckung — 1:1-Extension von User (userId @id + SSO-Felder). Kein eigenes passwordHash/totpSecret/status/disabledReason. Block B AdminUser braucht NEUES Modell oder Spec-Abschwächung.
User prisma/schema/accounts.prisma:1 Auth-Fundament: passwordHash, totpSecretEncrypted, totpEnabledAt, mfaRecoveryCodeHashes, DSGVO-Flags. Vorlage für AdminUser-Auth-Felder.
ImpersonationAudit prisma/schema/accounts.prisma:266 deckt M037-Audit (actor/target/tenant/action/reason/requestPath/metadata).
AuditEvent prisma/schema/core.prisma:55 deckt AdminAuditLog fachlich (Hash-Kette, tenantId?, actor/target/action/metadata, Indizes). Kein neues Schema nötig.
Role/Permission/RolePermission/UserRole/Group/GroupUser prisma/schema/permissions.prisma:1-78 RBAC-Fundament. Vorlage für AdminRole/AdminPermission (Block D).
Tenant, TenantUser, TenantUserInvitation prisma/schema/accounts.prisma:129/286/298 Tenant-Verwaltung Block G/H (Status via active, Membership, Invitations).
SubscriptionProduct…TenantSubscription, TenantFeatureOverride, Credit (14) prisma/schema/subscriptions.prisma Subscription-Management Block I (Stripe-IDs, Plan, Override).
FeatureFlag/FeatureFlagFilter/FeatureFlagAudit prisma/schema/featureFlags.prisma Block J (Modul 32).
Lead/LeadEvent/TenantAcquisition/MarketingIntegration prisma/schema/marketingLeads.prisma:14-143 Block M Lead-Inbox/Activity/Convert (operator-scoped, kein tenantId). Kein AdminDeal.
Feedback/SupportTicket prisma/schema/helpDesk.prisma:1/12 Block O (Aufnahme + Inbound-Email-Dedup). Keine Ticket-Messages/Konversation.
QueueFailedJob/ExportJob prisma/schema/queue.prisma Block K Worker-DLQ + Block G Export.
AppConfiguration, Log, MetricLog, Event prisma/schema/core.prisma Health/Config-Querschnitt Block K.
app.prisma (leerer Platzhalter) prisma/schema/app.prisma Vorgesehener Ort für neue HiveGrid-Admin-Modelle (AdminRole, AdminDeal, AdminTenantNote, Subprocessor, AvvVersion …).

Lücken / komplett neu zu bauen

  1. Eigenständige AdminUser-Identität (Block A/B, M034) — separate Tabelle mit email/passwordHash/totpSecret/totpEnabled/status/disabledReason/createdByAdminUserId getrennt von User. Heute existiert nur die User-Extension. Architektur-Entscheidung blockierend (siehe Kernbefund).
  2. AdminSession (Block C, M034) — server-side Postgres-Sessions mit 8h-Cap, 1h-Inaktivität, IP-Bindung (Re-Auth bei IP-Wechsel), Revoke-Liste. Boilerplate nutzt Cookie-Sessions (session.server.ts), kein DB-Session-Modell mit IP-Bindung → neu (Vorlage: packages/shared-store createSessionStore).
  3. AdminRole/AdminPermission/AdminRolePermission/AdminUserRole (Block D) — eigene parallele RBAC mit Bundle-Stufen (none/read/write/admin, viewer/operator/owner). Struktur aus permissions.prisma ableitbar, aber neue Tabellen + Default-Rollen-Seed (super_admin/support/sales/engineering/viewer) + Self-Permission-Schutz (letzter super_admin).
  4. AdminDeal + Deal-Pipeline/Kanban (Block M) — kein Deal-Modell, kein Kanban-View, kein Drag&Drop. expected_arr_eur, seats, stage. Komplett neu (Lead-Teil ist abgedeckt).
  5. AdminTenantNote (Block B/G) — pro-Tenant Markdown-Notizen mit Kategorie/Pin/Archiv. Kein Modell vorhanden. Neu.
  6. Subprozessoren- + AVV-Verwaltung (Block P, M041) — Subprocessor, AvvVersion (+ Re-Akzeptanz-Tracking) existieren nicht im Schema. Komplett neu (Querschnitt Modul 35).
  7. KWP-Sync-Health (Block K, M041) — kein KWP/Heartbeat-Modell/Code in der Boilerplate (HiveGrid-spezifische Integration, M089-M095). Komplett neu.
  8. Support-Ticket-Konversation (Block O) — AdminSupportTicketMessage (Reply-Thread, Internal-Notes, Attachments, Reaktions-Templates) fehlt; nur Single-Message-SupportTicket vorhanden. Erweitern.
  9. Worker-Queue-Steuerungs-UI (Block K) — Retry/Pause/Resume/Remove pro BullMQ-Queue: Worker-Runtime + DLQ-Modell existieren, aber keine Admin-UI/Steuerungs-API. Neu (auf apps/worker/admin-server.ts aufsetzen).
  10. Manuelle Tenant-Anlage mit Sonder-Konditionen (Block N, M036) — Slug-Live-Validation, Initial-Admin-Anlage, Trial-Dauer, Demo-Daten-Provisionierung, Reason-Pflicht. Tenant-Anlage existiert im Onboarding-/Registrierungs-Pfad, aber kein Admin-„Tenant-anlegen-im-Auftrag"-Flow. Neu (Teile aus Registration/Onboarding wiederverwenden).
  11. Dashboard-Erweiterung (Block F) — Churn/Expansion-MRR, ARPU, System-Health-Kacheln, Sales-Pipeline-Volumen, Support-Kennzahlen, Redis-Cache (TTL 5 Min) + Hourly-Aggregat-Job. Basis (Tenant/MRR/Active-Users) vorhanden, Rest neu.
  12. packages/ui-hivegrid Admin-Shell + Subframe-Adapter — der HiveGrid-eigene UI-Layer (ui-hivegrid, ui-subframe-Adapter) existiert in der Boilerplate nicht (nur Stubs ui-app/ui-subframe). Admin-Sidebar muss in packages/ui-hivegrid/src/app-shell/sidebar.config.ts registriert werden (INTEGRATION-CONTRACTS §2). Querschnitt für alle M034-M041.
  13. Impersonate 30-Min-Hard-Cap + Reason-Pflicht-Gate — State + Banner vorhanden, aber Spec verlangt harte 30-Min-Session-Begrenzung und Reason-Pflicht-Block (Block Q). Erweitern.

Empfohlenes Vorgehen (Reihenfolge)

Phase 0 — Architektur-Entscheidung (blockierend, vor M034):

  • Klären: getrennte AdminUser-Identität (Spec-treu, empfohlen) vs. Boilerplate-User-Extension (Change-Request gegen Pflichtenheft 37.1). Bis dahin keine Auth-Implementierung beginnen.

M034 (Auth) — zuerst aus BP übernehmen, Rest neu:

  1. Übernehmen (als-vorlage): auth.admin.login/logout-Flow, admin-mfa-gate.server.ts (Step-up-Gate inkl. fertiger Sensitive-Action-Taxonomie), login-rate-limit.ts, session-cookie.ts (Domain-Lock), adminPath-Routing.
  2. Neu: AdminUser/AdminSession-Modelle (in app.prisma), Email+Passwort+TOTP-Pflicht (Magic-Link verbieten), IP-Bindung, 8h/1h-Timeouts, 5/15 + 10/24h-Lockout, Bootstrap-Seed-Script.

M039 (Konten & Rollen) — RBAC: 3. AdminRole/AdminPermission/AdminUserRole als parallele RBAC (Struktur aus permissions.prisma, UI-Editor aus roles-and-permissions.tsx), Bundle-Stufen + Default-Rollen-Seed + Self-Permission-Schutz.

M035 (Dashboard) + M036 (Mandanten): 4. Dashboard: adminDashboardService + kpi.server als Basis, Health-/Pipeline-/Support-Kacheln + Redis-Cache + Hourly-Job ergänzen. 5. Mandanten: admin/accounts Liste/Detail erweitern (Status-Wechsel mit Reason → AuditEvent/ImpersonationAudit, AdminTenantNote neu, Trial-Verlängerung, Bulk-Email via notify/Campaign, Daten-Export via packages/exports). Manuelle Tenant-Anlage (Block N) neu.

M037 (Stellvertreter-Anmeldung): 6. Vorhandene Impersonation (Session-State + Banner + ImpersonationAudit) übernehmen; 30-Min-Hard-Cap + Reason-Pflicht-Gate (requireAdminMfaForAction("impersonation.start") ist schon da) + Banner-Text mit Ticket-Bezug ergänzen.

M038 (Mitarbeiter-Verwaltung): 7. admin/accounts/users als Vorlage; 2FA-Reset, Session-Revoke, Memberships, Deaktivieren auf neue Permission-Bundles umstellen; AdminUser-Verwaltung (Anlegen via Setup-Mail) neu.

M040 (Lead-Pipeline): 8. Lead/LeadEvent/marketing-leads-Routen + Convert-to-Tenant fast 1:1 übernehmen; AdminDeal-Modell + Kanban-Pipeline-UI + assigned_to/industry/company_size neu.

M041 (Health/Audit/Support/Legal): 9. Audit: audit-trails.tsx + logs.server + audit-pdf übernehmen (Volltext-Suche + JSON-Export ergänzen) — AuditEvent deckt AdminAuditLog. 10. Subscriptions-Admin: subscriptions/$id + Stripe erweitern (Override/Force-Sync/Refund/Diff-View). 11. Support: helpDesk + SupportTicket übernehmen; AdminSupportTicketMessage-Thread + Templates + Internal-Notes neu. 12. Health: metrics-Routen + Worker-Admin/Health-Server + Grafana als Basis; BullMQ-Queue-Steuerungs-UI (auf QueueFailedJob) + KWP-Sync (HiveGrid-spezifisch) neu. 13. Legal: Subprocessor/AvvVersion-Modelle + Re-Akzeptanz-Trigger (via notify/Campaign) komplett neu (Modul 35).

Querschnitt (durchgängig): withTenantScope/withPermission, auditEvent, notify, CatalogError, VMState, i18n-Keys + Sidebar-Registrierung in packages/ui-hivegrid (das zuerst angelegt werden muss) — gemäss AGENTS.md DoD + INTEGRATION-CONTRACTS.


Realitäts-Vorbehalte (keine Erfindungen)

  • packages/ui-hivegrid und ein gebauter ui-subframe-Adapter existieren nicht in der Boilerplate (nur Stubs). Die in AGENTS.md/INTEGRATION-CONTRACTS referenzierten Pfade sind HiveGrid-Soll, nicht Boilerplate-Ist.
  • Boilerplate-AdminUser ist kein parallel-Identity-Modell — das ist der zentrale Spec-Konflikt.
  • Kein AdminRole/AdminPermission/AdminSession/AdminAuditLog/AdminLead/AdminDeal/AdminLeadActivity/AdminSupportTicket/AdminTenantNote/Subprocessor/AvvVersion-Modell existiert (verifiziert via Grep über prisma/schema/).
  • Kein KWP-/Heartbeat-Code existiert (HiveGrid-spezifisch).
  • SupportTicket ist single-message (kein Konversations-Thread).
  • Admin-Login läuft heute via Authentik-OIDC, nicht Email+Passwort+TOTP wie Spec C verlangt.