Files
HiveGrid-Wireframes/hivegrid-cloud/docs/boilerplate-mapping/M33a-apps-engine.md
T

17 KiB

Boilerplate-Abgleich: M33a — Apps-Engine / Adapter-Layer

Feld Wert
Modul-ID M33a (Detail-Spec _bmad-output/specs/M33a-apps-engine.md)
Name Apps-Engine / Adapter-Layer
Milestones M008 (Adapter-Interface + State-Machine), M009 (Setup-Wizard + Sync-Log), M010 (Probe-Scheduler + Webhook-Sturm-Schutz)
Block Block 4 — USP-Säulen (_bmad-output/pflichtenheft/blocks/block4.md Modul 33a)
LPs LP-9 (Apps-Engine-Foundation), LP-10 (Klartext-Diagnostik), LP-11 (Adapter-Pattern für alle Integrationen)
Reuse-Level medium

Reuse-Verdict (kurz)

Das Daten-Modell ist fast 1:1 vorhanden (prisma/schema/appsEngine.prisma: App, DataConnection, AppSyncRun, AppSyncRunLog, AppSyncItem) — exakt die fünf Entitäten aus Spec Block B. Aber: Diese Modelle sind in der Boilerplate schema-only — es gibt keine Domänen-Logik, kein Adapter-Interface, keine State-Machine, keinen Setup-Wizard, keine Settings-UI, keinen Probe-Scheduler und keinen Webhook-Receiver dafür. Verifiziert per Grep: in apps/web/app, apps/worker/src, apps/api/src und allen packages/* (außer dem generierten Prisma-Client) existiert kein Code, der DataConnection/AppSyncRun/sample-data-sync verwendet.

Das eigentliche Engineering (M008-M010) muss neu gebaut werden — aber auf einem sehr starken Querschnitt-Fundament: AES-256-GCM-Credential-Encryption (CryptoApi), BullMQ-Queue mit Idempotenz + plan-basierten Prioritäten, Webhook-Signatur-Validierung (Stripe/MailerSend als HMAC-Vorlage), ein periodischer Worker-Scheduler (metrics-scheduler), eine fertige Connection-Management-Admin-Route als Vorlage (marketing-integrations.tsx inkl. Encryption-at-rest + Secret-Masking) und das Adapter-Registry-Pattern aus @toolctrl/marketing-outbound. Der WASM-plugin-runtime deckt die Phase-2-Marketplace-Foundation ab (M33b/M33c), ist für Phase 1 aber nicht der Kern.

Wichtige Begriffs-Abgrenzung (auch in der Inventur docs/boilerplate-inventory/integrations-ki.md §4 betont): Es gibt in der Boilerplate zwei „Apps-Engine"-Bedeutungen. (1) Die Data-Sync-Engine (appsEngine.prisma, App/DataConnection/AppSyncRun) = das, was M33a Phase 1 will. (2) Das WASM-Plugin-System (plugin-runtime/plugin-sdk/plugins.prisma) = M33a Phase 2 (Drittanbieter-Marketplace). Nicht verwechseln.


Übernehmbar aus Boilerplate

Boilerplate-Pfad Was Wie nutzbar
prisma/schema/appsEngine.prisma App, DataConnection, AppSyncRun, AppSyncRunLog, AppSyncItem — die fünf Spec-B-Entitäten anpassen — Felder/Enums an Spec angleichen (siehe „Lücken" unten)
apps/web/app/utils/api/.server/CryptoApi.ts AES-256-GCM Verschlüsselung (encrypt/decrypt, versioniert v1:iv:tag:ct, CRYPTO_SECRET) 1:1 für DataConnection.credentials „verschlüsselt at-rest" (Spec B, 33a.9.3 „Plattform-Schlüssel")
apps/web/app/routes/admin/marketing-integrations.tsx Komplette Connection-Management-Admin-Route: Liste, Create/Toggle/Delete, Permission-Gate (verifyUserHasPermission), Secret-Masking, lastDeliveredAt/lastError-Anzeige, i18n als-vorlage für die Settings-UI /settings/integrationen/ (Spec F)
apps/web/app/utils/leads/marketingIntegrations.db.server.ts Encryption-at-rest DB-Layer: SENSITIVE_KEYS, encryptSensitive/decryptSensitive, maskConfig über CryptoApi, Round-Trip als-vorlage für DataConnection-Persistenz mit verschlüsselten Credentials
packages/marketing-outbound/src/index.ts + src/types.ts Adapter-Interface + Registry-Pattern (adapterRegistry, resolveAdapter(type), MarketingOutboundAdapter<TConfig> mit parseConfig/send), adapterFetch() (Timeout + SSRF-Allowlist, nur HTTPS, kein RFC1918) als-vorlage für das Adapter-Interface der Apps-Engine (Spec A: connect/syncPull/syncPush/handleWebhook/validateConnection) + sicheres Outbound-Fetch
packages/queue/* (names.ts, payloads.ts, producers.ts, priority.ts, runtime.ts) BullMQ-Wrapper: typisierte Jobs, buildIdempotentJobId() (Idempotenz 33a.4.4), resolveJobPriorityForTenant() (plan-basiert), createQueue/createWorker 1:1 für Sync-Mechanik (Pull/Push/Webhook/Manual), Idempotenz-Keys, Sync-Lock
apps/worker/src/metrics-scheduler.ts Periodischer Poller-Pattern (30s/60s-Kadenzen, best-effort, started aus Worker-Entrypoint) als-vorlage für den Probe-Scheduler (M010: aktiv 5min / eingeschränkt 1min / defekt 15min)
apps/api/src/webhooks/mailersend-signature.ts HMAC-Signatur-Validierung mit timingSafeEqual, Timestamp-Toleranz, typisierte Failure-Reasons als-vorlage für Webhook-Signatur-Validierung pro App (Spec E.3, offener Punkt der Spec)
apps/api/src/billing/stripe-webhook-route.ts Inbound-Webhook-Route mit Signatur-Konstruktion, Outbox-Publish in DB-Transaktion, Metrics, Error-Envelope als-vorlage für den Webhook-Receiver app.hivegrid.de/api/v1/webhooks/{app_key}/{tenant_id}/{connection_id} (Spec E.3)
apps/api/src/webhookDeliveryQueue.ts + WebhookDeliveryJob (@toolctrl/queue) Outbound-Webhook-Delivery über Queue (buildWebhookDeliveryJob, signierte/retried Zustellung) anpassen für Push-Sync / signierte Outbound-Webhooks (Spec E.2)
packages/storage/src/index.ts (StorageAdapter, createS3StorageAdapter) + signed/ Scaleway-S3-Adapter + Signed-URLs als-vorlage für den kwpsync.exe-Download im Setup-Wizard (Spec D, connection_type windows_client)
apps/web/app/utils/integrations/githubService.ts Beispiel eines konkreten externen-Service-Adapters (OAuth/Token-Handling-Muster) als-vorlage für die App-spezifischen Adapter (eigene Module: KWP/Gmail/Stripe)
packages/plugin-runtime/* + packages/plugin-sdk/* + prisma/schema/plugins.prisma WASM-Sandbox, Capability-Gateway (deny-by-default), Manifest+Ed25519-Signatur, Hook-Registry, Audit-Chain, Crash-Tracker; Plugin/TenantPluginCapabilityGrant/PluginInvocation als-vorlage ausschließlich für Phase 2 (M33b Community-Marketplace mit Sandboxing/Review, Spec Block I) — nicht Phase-1-Kern
packages/plugins/src/manifest-schema.ts (FeatureManifest, validateFeatureManifestShape) Feature-/App-Manifest-Schema (Surfaces/Workers/Provider/Permissions/Audit) als-vorlage für das Manifest-Format der Adapter-Registry (Spec C manifest.ts)

Querschnitt, das M33a wie jedes Modul mitnimmt (separate Foundation-Module M001-M011)

  • Audit: automatisch via M001-Prisma-Middleware (AGENTS.md §C.13); externe Webhook-Aufrufe manuell via auditEvent (INTEGRATION-CONTRACTS §6). Deckt AV #6 (Audit für Connection-Änderungen).
  • Notifications: via notify() (M011, INTEGRATION-CONTRACTS §7) — für degraded/broken-Alerts (Spec G, 33a.3.5). Realtime/In-App über @toolctrl/realtime (SSE).
  • Mail: @toolctrl/mail (MailerSend, EU) für Email-Benachrichtigungen.
  • i18n: M003-Build-Lint; pro-App i18n/de.json Klartext-Übersetzungen (Spec C/G).
  • Feature-Flags: M006 — pro App phase/requires_subscription_feature + Feature-Flag (Spec C Tenant-Sicht).
  • Permissions: M004 withTenantScope() + withPermission(); verifyUserHasPermission als bestehendes Boilerplate-Muster.

Vorhandene Daten-Modelle

Quelle: /Users/raffaelsheikh/Documents/GitHub/boilerplate/prisma/schema/appsEngine.prisma (generierter Client: packages/db/generated/prisma/client/models/{App,DataConnection,AppSyncRun,AppSyncRunLog,AppSyncItem}.ts).

Boilerplate-Modell Deckt Spec-Entität Vorhandene Felder (Auszug) Bewertung
App App (Spec B) id, tenantId, type, config (JSON), icon, isActive, installedByUserId, syncRuns[], @@unique([tenantId, type]) Teilweise. In BP tenant-scoped (tenantId), Spec will App plattform-weit (Code-Registry-Spiegel). Es fehlen key/name/description/category/connection_type/connection_schema/capabilities[]/phase/requires_subscription_feature/documentation_url.
DataConnection DataConnection (Spec B) id, tenantId, name, type, config (Kommentar „Encrypted JSON credentials"), description Solide Basis. Keine FK zu App in BP (Spec will app_id), kein connection_status-Enum, keine last_health_check_*/last_sync_at/next_sync_at/last_error/metadata/created_by_user_id. Multi-Connection-pro-App-pro-Tenant ist mit name schon angelegt.
AppSyncRun AppSyncRun (Spec B) id, appId(FK), tenantId, taskKey/taskName, status (pending/running/completed/partial/failed/cancelled/reverted), executionMode (manual/scheduled/webhook), startedAt/completedAt, duration, itemsProcessed/Created/Updated/Failed, error, createdByUserId, logs[], syncItems[] Sehr gute Übereinstimmung. FK zeigt auf App, Spec will FK auf DataConnection (data_connection_id). kind (pull/push/webhook/health_check/manual_resync) vs. BP executionMode (manual/scheduled/webhook) — angleichen. summary_text (Klartext) fehlt; itemsSucceeded als itemsProcessed - itemsFailed ableitbar.
AppSyncRunLog AppSyncRunLog (Spec B) id, syncRunId(FK), type (info/success/warning/error), message, metadata Gute Basis. severity der Spec (debug/info/warn/error/critical) ⊃ BP-type; timestamp fehlt (nur createdAt); tech_details = metadata.
AppSyncItem AppSyncItem (Spec B) id, syncRunId(FK), objectType, sourceId, destinationId, status (synced/failed/skipped/pending/reverted), action, sourceData/destinationData (JSON), error, rolledBackData/rolledBackAt Sehr gute Übereinstimmung, sogar mehr (Rollback-Felder, die die Spec nicht explizit fordert). Spec operation (create/update/delete/upsert/noop) vs. BP action (created/updated/deleted/skipped) — angleichen. entityType/entityId (HiveGrid-Entität) = BP objectType/destinationId.

Phase-2-Modelle (Marketplace) — vorhanden in prisma/schema/plugins.prisma: Plugin, TenantPluginCapabilityGrant, PluginUserConfig, PluginInvocation, PluginCapabilityUse (mit per-Tenant Hash-Chain). Deckt die Spec-B-Phase-2-Entitäten (CommunityApp, CommunityAppInstall) konzeptionell ab, aber mit anderem Namensschema. Nicht für Phase 1 verwenden.

Nicht vorhanden: kein App-Registry-Drift-Tracking-Modell, keine Webhook-Rate-Limit-/Anomalie-State-Tabelle, kein Schema-Drift-Sentinel-State.


Lücken / komplett neu zu bauen

M008 — Adapter-Interface + State-Machine (neu)

  1. Adapter-Interface (app/integrations/{app-key}/index.ts-Konvention, Spec A/C): connect/disconnect/refreshTokens/validateConnection/syncPull/syncPush/handleWebhook + capabilities[]/triggers[]/actions[] + connection_schema. Vorlage: marketing-outbound-Adapter-Registry, aber das konkrete Interface existiert nicht.
  2. 5-Status-State-Machine pending → active → degraded → broken → revoked (Spec G, 33a.3.1) mit Audit-Eintrag pro Übergang + Klartext-Hinweis pro Status. Existiert nicht (BP DataConnection hat keinen Status-Enum). connection_status-Feld + Enum neu.
  3. Adapter-Registry / Build-Time-Scan von app/integrations/ + DB-Sync der Manifests + Drift-Check (Spec C). Existiert nicht (Manifest-Schema-Vorlage in @toolctrl/plugins).
  4. Dummy-App als Referenz-Implementierung (M008-Erfolgskriterium). Neu.

M009 — Setup-Wizard + Sync-Log (neu)

  1. Generischer Setup-Wizard pro Connection-Type (OAuth2 / API-Key / Username-Password / Windows-Client), Form-Generator aus connection_schema (Spec D, 33a.2). UI komplett neu (Vorlage: marketing-integrations.tsx für die Listen-/CRUD-Hülle).
  2. OAuth2-Redirect-Flow + Token-Refresh-Worker (Spec D). Kein generischer OAuth-Client in BP (authProviders.server.ts ist Auth-Login, nicht App-Connection-OAuth; @ai-sdk/openai/remix-auth-google per EU-Constraint verboten). Neu.
  3. Sync-Log-UI mit Filter (Status/Operation/Datum) + Detail-Schublade + Klartext-summary_text (Spec F, 33a.4). Neu.
  4. Disconnect-Flow mit Multi-Step-Confirm + Cleanup (Webhook-Subscriptions kündigen, Tokens revoken) + status=revoked statt Hard-Delete (Spec D, 33a.7.4). Neu.

M010 — Probe-Scheduler + Webhook-Sturm-Schutz (neu)

  1. Probe-Scheduler mit status-adaptiver Frequenz (active 5min / degraded 1min / broken 15min, Spec G/33a.3.4). Vorlage: metrics-scheduler.ts (Poller-Pattern) + @toolctrl/queue Repeatable-Jobs — die konkrete Logik neu.
  2. Webhook-Sturm-Schutz (Hard-Limit Events/Stunde pro Mandant, Default 1000) + Verwerfen-mit-Notification (Spec E, 33a.5.1, AV A.16.1). Rate-Limiter-Vorlage existiert in @toolctrl/ai/guards (createFixedWindowAIRateLimiter), aber nicht für Webhooks. Neu.
  3. Anomalie-Erkennung (10x normales Volumen → Pause + Klartext, Spec E, 33a.5.2, AV A.16.2): Rolling-Window-Average + Threshold. Neu.
  4. Schema-Drift-Sentinel (validateSchema(), Spec E/33a.6): Pause + Plattform-Admin-Alert (KWP-spezifisch in M092). Neu.
  5. Webhook-Receiver-Route api/v1/webhooks/{app_key}/{tenant_id}/{connection_id} + per-App-Signatur-Validierung (Spec E.3). Routen-/HMAC-Vorlage in stripe-webhook-route.ts + mailersend-signature.ts, der generische Multi-App-Receiver neu.

Querschnitt / Wiring (neu pro Modul, aber Foundation vorhanden)

  1. Sidebar-Eintrag Einstellungen → Integrationen (Apps) (INTEGRATION-CONTRACTS §1, Route app.hivegrid.de/settings/integrationen/). Neu in packages/ui-hivegrid/src/app-shell/sidebar.config.ts (Datei selbst existiert in HiveGrid noch nicht — Repo ist Greenfield).
  2. 6 Permissions integrations.read/connect/disconnect/manual_sync/view_logs/admin (Spec H) — in packages/entitlements/src/permissions.ts + Default-Rollen-Mapping (GF/Vertriebsleiter/Büro). Permission-Pattern existiert (permissions-seed.server.ts), die Keys neu.
  3. View-Model-Layer (packages/view-models/**) + UI-Adapter (packages/ui-hivegrid/src/adapters/) — gemäß AGENTS.md Code-Layer-Trennung. Diese Pakete existieren in der Boilerplate noch nicht (sind HiveGrid-Eigenbau laut AGENTS.md „Du erweiterst, was fehlt").
  4. Klartext-Fehler-Catalog-Einträge (M002) pro Fehler-Code + Lösungs-Hinweis (Spec G/33a.10). Neu.

Repo-Realität (wichtig)

  1. Das HiveGrid-Cloud-Repo enthält aktuell NUR Planungs-Artefakte (_bmad, _bmad-output, docs, prisma, AGENTS.md) — kein apps/, packages/, kein package.json. Verifiziert per ls. Die Boilerplate muss erst als Codebase ins Repo gezogen werden (AGENTS.md: „Die Boilerplate IST deine Codebase"). Bis dahin gibt es nichts zu erweitern — der Pre-Flight-Check aus AGENTS.md (package.json/apps//packages/ vorhanden) schlägt fehl.

Empfohlenes Vorgehen

Reihenfolge (zuerst BP übernehmen, dann neu bauen):

  1. Voraussetzung: Boilerplate als Codebase ins HiveGrid-Repo bringen + EU-Sterilisations-Check (AGENTS.md Pre-Flight). Vorher kann M008 nicht starten.

  2. Daten-Layer (BP anpassen): prisma/schema/appsEngine.prisma als Basis nehmen und an Spec B angleichen:

    • App: plattform-weit machen (oder zweigeteiltes Modell App-Definition vs. installierte App klären), Felder key/name/description/category/connection_type/connection_schema/capabilities/phase/requires_subscription_feature/documentation_url ergänzen.
    • DataConnection: FK app_id, connection_status-Enum (5 Status), last_health_check_*/last_sync_at/next_sync_at/last_error/metadata/created_by_user_id. Credentials über CryptoApi (1:1) verschlüsseln — Vorlage marketingIntegrations.db.server.ts.
    • AppSyncRun/AppSyncRunLog/AppSyncItem: FK-Ziel auf DataConnection, kind/severity/operation/summary_text angleichen. Forward-Only-Migration mit Inverse-SQL-Kommentar (AGENTS.md §F.28).
  3. M008 (Adapter-Interface + State-Machine): Adapter-Interface nach Vorbild @toolctrl/marketing-outbound (Registry + parseConfig/send → erweitern zu connect/sync*/handleWebhook/validateConnection). Outbound-Calls über adapterFetch() (SSRF-/Timeout-Guard). State-Machine als Enum-Transitions mit Audit pro Wechsel (M001-Middleware deckt DB-Audit, externe Calls via auditEvent). Dummy-App als Referenz. Manifest-Schema nach Vorbild @toolctrl/plugins.

  4. M009 (Setup-Wizard + Sync-Log): Settings-Route nach Vorbild marketing-integrations.tsx (Liste/CRUD/Permission-Gate/Secret-Masking/i18n) → erweitern zum Wizard + Sync-Log-UI. View-Model-Layer + UI-Adapter neu (AGENTS.md Code-Layer-Disziplin). Jobs über @toolctrl/queue mit buildIdempotentJobId (Idempotenz 33a.4.4) + resolveJobPriorityForTenant.

  5. M010 (Probe-Scheduler + Schutz): Probe-Scheduler nach Vorbild metrics-scheduler.ts + Queue-Repeatable-Jobs, status-adaptive Frequenz. Webhook-Receiver-Route nach Vorbild stripe-webhook-route.ts, Signatur nach mailersend-signature.ts. Rate-Limiter + Anomalie-Detector + Schema-Drift-Sentinel neu. Notifications strikt über notify() (M011).

  6. Phase 2 (separat, M33b/M33c): Erst nach Geerkens-Launch. WASM-plugin-runtime/plugin-sdk/plugins.prisma als Foundation für den Drittanbieter-Marketplace (Sandboxing/Capability-Consent/Signatur/Audit-Chain). Achtung: in der BP sind in Prod nur log/audit-Capabilities freigeschaltet (PLUGIN_AVAILABLE_HOST_CAPABILITY_NAMES).

Querschnitt nicht vergessen (DoD-Block): Sidebar-Eintrag (Einstellungen-Gruppe), 6 Permissions, i18n-Keys, Feature-Flag, Klartext-Catalog, Smoke-Tests + Hot-Swap-Drill + Visual-Snapshot, Permission-Denied → 404.