customer cases soluttion architecture

This commit is contained in:
ValueOn AG 2026-06-04 23:20:41 +02:00
parent d6f0b824bf
commit c3e1eb74e8
10 changed files with 1528 additions and 989 deletions

View file

@ -1,572 +0,0 @@
<!-- status: plan -->
<!-- started: 2026-04-16 -->
<!-- component: gateway | ui-nyla | platform -->
<!-- replaces: local/notes/demo-tue-use-cases-inputs-customers.md, c-work/1-plan/2026-04-demo2-merged-customer-trustee-plan.md, c-work/1-plan/2026-04-porta-ui-enhancements-team-meeting.md -->
# Konsolidierter Kundenwünsche-Plan — PORTA Umsetzung
> **Stand:** 16. April 2026 (aktualisiert mit PWG-Workshop-Ergebnissen)
> **Zweck:** Einheitliche Übersicht aller Kundenwünsche, priorisiert und gegen die Codebase abgeglichen.
> **Ersetzt:** `local/notes/demo-tue-use-cases-inputs-customers.md`, `c-work/1-plan/2026-04-demo2-merged-customer-trustee-plan.md`, `c-work/1-plan/2026-04-porta-ui-enhancements-team-meeting.md`
---
## Kunden-Übersicht
| Kunde | Branche | Kontakte | Hauptinteresse | Status |
|-------|---------|----------|----------------|--------|
| **Bling** | Treuhandbüro | KJS | Belegverarbeitung, Budget, Dashboards, Mandantenmanagement | Trial geplant |
| **PWG** (Stiftung) | Immobilien/Wohnen (~300 Liegenschaften, 78 Pers.) | MB | **Pilot: Jahresmietzinsbestätigungen** (3'200/Jahr), Belegverarbeitung Abacus, CommCoach, Neutralisierung, Knowledge-Retrieval | Workshop 16.04.2026 ✅ — Pilot bestätigt, Versand Sommer 2026 |
| **Quid / ServiceHunter** | SaaS/Dienstleistung | DC | KPI-Dashboard, Zeiterfassung, Prognosen, Konsolidierung | Follow-up geplant |
---
## Legende Codebase-Status
| Symbol | Bedeutung |
|--------|-----------|
| ✅ | Im Code vorhanden und funktional |
| 🔧 | Grundstruktur vorhanden, Anpassung/Ergänzung nötig |
| ❌ | Noch nicht umgesetzt |
| ⏸️ | Bewusst zurückgestellt (wartet auf Input/Entscheid) |
---
## Teil 1: Feature-Anforderungen (Kunden-Use-Cases)
### 1.1 Automatisierte Belegverarbeitung & Spesenverwaltung
**Kunden:** Bling (Prio hoch), PWG, Quid (Spesen)
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|---|-------------|-----------------|---------------------|
| 1.1.1 | Spesenbelege per Foto → automatische Klassifikation (Rechnung, Spesenbeleg, Bankauszug) | ✅ | `methodTrustee/actions/extractFromFiles.py` + `processDocuments.py` — Pipeline extrahiert, klassifiziert, verbucht |
| 1.1.2 | SharePoint-Synchronisation (automatisch, z.B. täglich 22:00) | ✅ | `nodeDefinitions/sharepoint.py` — 6 Nodes; `automation2/scheduleCron.py` für Zeitsteuerung; System-Template "Treuhand: PDF-Klassifizierung & Trustee-Import" in `interfaceBootstrap.py` |
| 1.1.3 | Automatische Kontierung basierend auf Kontoplan | ✅ | In `processDocuments.py` — AI-gestützte Kontierung gegen Feature-Daten (Kontoplan via Accounting-Bridge) |
| 1.1.4 | Firmen-Mapping zu Kunden/Lieferanten | 🔧 | Grundstruktur in Accounting-Bridge; kein dediziertes Mapping-UI oder regelbasiertes Matching |
| 1.1.5 | Optionales Tagging (z.B. "Fuel Station") | 🔧 | Tags auf Dokument-Ebene möglich; kein Beleg-spezifisches Tag-System |
| 1.1.6 | Buchungsregeln für wiederkehrende Belege | ❌ | Kein regelbasiertes Booking-Template-System |
| 1.1.7 | Vorsteuer automatisch hinterlegen und auslesen | 🔧 | Accounting-Connectors liefern Steuerdaten; automatische MWST-Zuordnung bei Belegverarbeitung nicht explizit |
| 1.1.8 | Integration RunMyAccounts | ✅ | `accountingConnectorRma.py` |
| 1.1.9 | Integration Bexio | ✅ | `accountingConnectorBexio.py` |
| 1.1.10 | Integration Abacus | ✅ | `accountingConnectorAbacus.py` |
| 1.1.11 | Integration Xero | ❌ | Kein `accountingConnectorXero.py` — kein Code vorhanden |
| 1.1.12 | PDF/Excel/Word/Zip Verarbeitung | ✅ | Extraktoren vorhanden; UDM-Konzept in `0-ideas/unified-document-model.md` |
### 1.2 Budget / Soll-Ist-Vergleich
**Kunden:** Bling (Prio hoch), Quid (KPI-Kontext)
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|---|-------------|-----------------|---------------------|
| 1.2.1 | Budget-Excel hochladen und gegen Live-Daten prüfen | 🔧 | Prompt-Template "Budget-Vergleich" in `mainTrustee.py` (Quick Action + Template Workflow); Frontend `TrusteeAnalyseView.tsx` hat Budget-Tab mit Upload; **aber kein Demo-Budget-Excel vorhanden** |
| 1.2.2 | Vergleiche über Perioden (Q1 aktuell vs. Vorjahr vs. Budget) | ✅ | Im Prompt-Template als Anweisung an AI-Agent enthalten |
| 1.2.3 | Automatische Diagramm-Erstellung | ✅ | Agent erzeugt Charts via `aggregateTable` + AI-Prompt |
| 1.2.4 | Live-Daten via API (kein PDF-Export nötig) | ✅ | `refreshAccountingData` Action synct Live-Daten; API-basiert |
| 1.2.5 | Caching konfigurierbar | ✅ | `_featureQueryCache` mit TTL 300s in `_featureSubAgentTools.py` |
| 1.2.6 | Abweichungen mit Begründung | ✅ | Im Prompt-Template: Agent soll Abweichungen erklären |
| 1.2.7 | Vorausschauende Prognosen | ✅ | Separates Prompt-Template "Prognose/Trend-Analyse" |
### 1.3 Cashflow-Rechnung
**Kunden:** Bling
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|---|-------------|-----------------|---------------------|
| 1.3.1 | Plausibilisierung und Erstellung Cashflow-Rechnung | ✅ | Prompt-Template "Cashflow-Rechnung" in `mainTrustee.py` |
| 1.3.2 | Nicht-relevante Positionen berücksichtigen | ✅ | Im Prompt-Template als Anweisung |
| 1.3.3 | Warnungen bei kritischen Werten | ✅ | Im Prompt-Template |
### 1.4 Dashboard — Bilanz- & Erfolgsrechnungsanalyse
**Kunden:** Bling, Quid
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|---|-------------|-----------------|---------------------|
| 1.4.1 | KPI-Dashboard (Bruttogewinn, ROI, Gewinn etc.) | ✅ | Prompt-Template "KPI-Dashboard" + Quick Action + `TrusteeAnalyseView.tsx` KPI-Tab |
| 1.4.2 | Check hälftiger Kapitalverlust | ✅ | Im Jahresabschluss-Prompt enthalten |
| 1.4.3 | Überschuldungs-Check | ✅ | Im Jahresabschluss-Prompt enthalten |
| 1.4.4 | Durchschnittliche Zahlungsfrist | 🔧 | Nicht als dedizierter KPI; Agent kann es berechnen wenn Daten vorhanden |
### 1.5 Liquiditätsplanung
**Kunden:** Bling
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|---|-------------|-----------------|---------------------|
| 1.5.1 | Liquiditätsplanung analog Budgetplanung | 🔧 | Kein dediziertes Prompt-Template; über Prognose-Template teilweise abdeckbar |
| 1.5.2 | Automatische Erstellung aus Vergangenheit | 🔧 | Agent kann historische Daten analysieren; kein dedizierter Workflow |
| 1.5.3 | Zusätzliche Inputs (z.B. ausserordentliche Dividende) | ❌ | Kein Mechanismus für manuelle Zusatz-Inputs in Prognose |
### 1.6 Gastro-Use-Case — Echtzeit-Rentabilitätsanalyse
**Kunden:** Bling (Prio hoch, bestes Beispiel für Kunden-Mehrwert)
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|---|-------------|-----------------|---------------------|
| 1.6.1 | Integration Kassensystem + Lohndaten + Buchhaltung | ⏸️ | **Wartet auf Kevin-Input** — kein Connector für Kassensysteme/Virux |
| 1.6.2 | Tagesumsatz vs. Personalkosten vs. Wareneinsatz | ⏸️ | Konzeptionell über generischen Data-Import möglich |
### 1.7 Abschlussunterstützung
**Kunden:** Bling, allgemein Treuhand
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|---|-------------|-----------------|---------------------|
| 1.7.1 | Jahresabschluss-Checks | ✅ | Prompt-Template "Jahresabschluss prüfen" in `mainTrustee.py` |
| 1.7.2 | Abgrenzungsbuchungen vorbereiten | 🔧 | Im Prompt adressiert; keine dedizierte Automation |
| 1.7.3 | Bilanzkonti prüfen / Saldovalidierung | ✅ | Im Jahresabschluss-Prompt |
| 1.7.4 | Vorjahresvergleiche | ✅ | In mehreren Prompt-Templates |
### 1.8 Zentrales Mandantenmanagement
**Kunden:** Bling (verschiedene Systeme über eine Schaltzentrale)
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|---|-------------|-----------------|---------------------|
| 1.8.1 | Verschiedene Kunden auf verschiedenen Systemen verwalten | ✅ | Multi-Tenant-Plattform ist Kernarchitektur; `accountingRegistry.py` unterstützt verschiedene Connectors pro Mandant |
| 1.8.2 | Ein Login, alle Mandanten | ✅ | Plattform-Feature: Mandantenwechsel im UI |
| 1.8.3 | Strikte Datentrennung | ✅ | Mandantenisolation auf DB- und API-Ebene |
---
### 1.9 PWG — Stiftung für preisgünstiges Wohnen
**Kontext:** ~300 Liegenschaften, Team 78 Personen. IT-Leiter Markus Brütsch (seit 2+ Jahren). Neue Rolle "Organella" für Digitalisierung (Schnittstelle Technologie/Betrieb, kein IT-Hintergrund). PWG evaluiert AI-Lösungen offen, noch keine Entscheidung getroffen. Workshop 16.04.2026 durchgeführt.
**Pilotprojekt bestätigt:** Jahresmietzinsbestätigungen (siehe 1.9.9).
#### 1.9a Plattform-Features (bestehend)
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|---|-------------|-----------------|---------------------|
| 1.9.1 | Automatisierte Belegverarbeitung mit Abacus | ✅ | `accountingConnectorAbacus.py` + Trustee-Pipeline |
| 1.9.2 | Kommunikations-Coach für Mietergespräche | ✅ | `features/commcoach/` — komplett inkl. 10+ Personas |
| 1.9.3 | Immobilien-Personas (Zahlungsrückstand, Nebenkosten, Einzug, Lärm) | ✅ | 4 PWG-Personas in `BUILTIN_PERSONAS` + Seeding |
| 1.9.4 | KI-Arbeitsplatz mit Datenneutralisierung | ✅ | `features/neutralization/` — PII-Masking, Playground, Private-LLM; Daten-Residency Schweiz |
| 1.9.5 | PWG-Agent (Stiftungsstil, öffentliche PDFs als Futter) | 🔧 | Knowledge-Base-Feature vorhanden; kein PWG-spezifisches Knowledge-Set (Geschäftsberichte, Vermietungsreglement, Führungshandbuch etc.) |
| 1.9.6 | M365-Anbindung (SharePoint, Outlook, OneDrive, Teams) | ✅ | SharePoint-Nodes + Outlook-Methode in Workflows; nutzt nativen SharePoint-Index |
| 1.9.7 | KI-Auswertung Abacus-Daten/Reports | ✅ | Über Trustee-Feature + `aggregateTable` + AI-Prompts; Read/Write via Abacus-API |
| 1.9.8 | Grundstücksanalyse (öffentliche Daten: GIS, Maps, Grundbuch) | ❌ | Kein Connector/Workflow für öffentliche Geodaten |
#### 1.9b Neue Anforderungen aus Workshop 16.04.2026
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|---|-------------|-----------------|---------------------|
| 1.9.9 | **Pilotprojekt: Jahresmietzinsbestätigungen** (ca. 700800 Schreiben/Quartal, Versand Sommer 2026) | ❌ | Kein dedizierter Workflow — siehe Workflow-Design unten |
| 1.9.10 | FileMaker-Integration (Portfolio, Liegenschaften, Erneuerungsplanung, Bauprojekte, Akquisition) | ❌ | Kein FileMaker-Connector; Datenmenge/-qualität muss geprüft werden |
| 1.9.11 | Template-basierte Dokumentenerstellung (HTML-Templates → Word mit Corporate Design) | 🔧 | Code-Editor mit Claude vorhanden; kein Template-to-Word-Pipeline |
| 1.9.12 | Notification-System (reagiert auf DB-Änderungen, Berichte per E-Mail, Workflow-Trigger) | 🔧 | E-Mail-Versand in Workflows vorhanden (`methodOutlook`); kein generisches DB-Change-Detection-System |
| 1.9.13 | Information Retrieval über diverse Wissensquellen (Guidelines, Handbücher, SharePoint) | 🔧 | Knowledge-Base + SharePoint-Index vorhanden; kein PWG-spezifisches Datenset geladen |
| 1.9.14 | Datenvalidierung als Erst-Schritt (welche Daten korrekt/aktuell?) | ❌ | Kein Daten-Audit-Workflow |
| 1.9.15 | Compliance & Audit: vollständiges Tracking aller AI-Transaktionen | ✅ | `ComplianceAuditPage.tsx` + Gateway-Logging; jede Anfrage protokolliert |
| 1.9.16 | Granulare Neutralisierungs-Kontrolle pro Datenquelle | ✅ | In Neutralisierungs-Feature konfigurierbar pro Source |
#### 1.9c Pilot-Workflow: Jahresmietzinsbestätigungen
**Business Case:** 4 × 800 Schreiben/Jahr = 3'200 Schreiben. Aktuell: Serienbrief → manueller Versand → Scan der Rückantworten → manuelle Verarbeitung. Ziel: AI-gestützte Verarbeitung der gescannten Rückantworten mit Antwortvorschlägen.
**Workflow-Design (67 Schritte, davon 1 mit AI):**
```
┌─────────────────────────────────────────────────────────────────┐
│ PWG Pilot: Jahresmietzinsbestätigungen │
│ │
│ Phase 1: Generierung (bestehend bei PWG) │
│ ┌──────────────────────────────────────┐ │
│ │ System generiert Serienbrief │ (PWG-internes System) │
│ │ mit aktuellen Mietdaten │ │
│ └──────────┬───────────────────────────┘ │
│ ▼ │
│ Phase 2: Versand & Rücklauf (manuell) │
│ ┌──────────────────────────────────────┐ │
│ │ Manueller Versand + Scan der │ │
│ │ Rückantworten → SharePoint-Ordner │ │
│ └──────────┬───────────────────────────┘ │
│ ▼ │
│ Phase 3: PowerOn-Workflow (automatisiert) │
│ │
│ Step 1: trigger.schedule (täglich oder on-demand) │
│ ▼ │
│ Step 2: sharepoint.listFiles (Scan-Ordner, neue Dokumente) │
│ ▼ │
│ Step 3: flow.loop (für jedes gescannte Dokument) │
│ ▼ │
│ Step 4: sharepoint.downloadFile + trustee.extractFromFiles │
│ → OCR/Extraktion: Mietername, Adresse, Bestätigung, │
│ Anmerkungen, Unterschrift ja/nein │
│ ▼ │
│ Step 5: ai.prompt ← EINZIGER AI-SCHRITT │
│ → Gescannte Daten gegen Originaldaten prüfen │
│ → Status klassifizieren (bestätigt / Abweichung / │
│ fehlende Unterschrift / unleserlich) │
│ → Antwortvorschlag generieren bei Abweichung │
│ ▼ │
│ Step 6: data.writeToTable (Ergebnis in Übersichtstabelle) │
│ ▼ │
│ Step 7: email.send (Zusammenfassung an Sachbearbeiter) │
│ → Audit-Log für jeden Verarbeitungsschritt │
└─────────────────────────────────────────────────────────────────┘
```
**Benötigte Komponenten für den Pilot-Workflow:**
| # | Komponente | Codebase-Status | Was zu tun ist |
|---|-----------|-----------------|----------------|
| W1 | `trigger.schedule` oder `trigger.manual` | ✅ | Vorhanden in `nodeDefinitions/triggers.py` |
| W2 | `sharepoint.listFiles` + `sharepoint.downloadFile` | ✅ | Vorhanden in `nodeDefinitions/sharepoint.py` |
| W3 | `flow.loop` | ✅ | Vorhanden in `nodeDefinitions/flow.py` |
| W4 | `trustee.extractFromFiles` (OCR/Extraktion gescannter Dokumente) | ✅ | Vorhanden; OCR für einseitige Scans unterstützt |
| W5 | `ai.prompt` — Prompt-Template "Mietzinsbestätigung prüfen" | ❌ | **Neues Prompt-Template** nötig: Scan-Daten gegen Originaldaten abgleichen, Status klassifizieren, Antwortvorschlag generieren |
| W6 | Ergebnis-Tabelle / Übersichtsliste (verarbeitete Bestätigungen) | 🔧 | `data`-Nodes existieren; kein dedizierter "Mietzinsbestätigungs-Report"-Output |
| W7 | `email.send` (Zusammenfassung an Sachbearbeiter) | ✅ | Vorhanden via `methodOutlook` |
| W8 | Abacus-Referenzdaten (Original-Mietzinsdaten für Abgleich) | 🔧 | Abacus-Connector vorhanden; Abfrage der Mietzins-Stammdaten muss konfiguriert werden |
| W9 | Audit-Logging für gesamten Prozess | ✅ | Plattform-Feature: alle AI-Transaktionen geloggt |
| W10 | Graph-Editor Workflow als Template speichern | ❌ | Workflow muss im Editor gebaut und als System-Template gespeichert werden |
**Voraussetzungen (Action Items aus Workshop):**
| # | Action Item | Verantwortlich | Status |
|---|------------|----------------|--------|
| AI1 | API-Zugang zu Abacus-Testmandant einrichten | Patrick Motsch | ❌ offen — Patrick koordiniert mit Abacus |
| AI2 | PWG muss Zugriff auf Testmandant bestätigen | PWG (Markus) | ❌ offen |
| AI3 | Preismodell bereitstellen (Grundgebühr/User/Monat + Token-Gebühr) | PowerOn | ❌ offen |
| AI4 | Datenschutzanforderungen und Vertragsklauseln für Lieferanten prüfen | PWG | ❌ offen |
| AI5 | Prozessschritte Pilot ausarbeiten und Kalkulation erstellen | PowerOn | 🔧 Workflow-Design in diesem Dokument; Kalkulation offen |
| AI6 | FileMaker-Datenmenge und -qualität prüfen (potenzielle Integration) | PWG + PowerOn | ❌ offen |
---
### 1.10 Quid / ServiceHunter Use Cases
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|---|-------------|-----------------|---------------------|
| 1.10.1 | KPI-Dashboard (Kundenmargen, ACV, Lifetime Value, Produktionsmarge) | 🔧 | Generisches KPI-Prompt-Template vorhanden; kundenspezifische KPIs brauchen Daten-Import |
| 1.10.2 | Zeiterfassung & Support-Analyse (Zendesk-Verknüpfung) | ⏸️ | **Kein Zendesk-Connector** — bewusst CSV-Upload-Workaround |
| 1.10.3 | Prognosen & Proaktive Steuerung | ✅ | Prognose-Prompt-Template vorhanden |
| 1.10.4 | Konsolidierung international (CH, DE, UK) | ⏸️ | **Wartet auf Lars-Meeting** — hohe Komplexität |
| 1.10.5 | Spesen-Automatisierung (SharePoint/Drive → verbuchen) | ✅ | SharePoint-Pipeline + Trustee-Import vorhanden |
---
## Teil 2: UI/UX-Anforderungen (aus Team-Meeting / Nutzertests)
### 2.1 AI-Workspace Usability
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|---|-------------|-----------------|---------------------|
| 2.1.1 | Primäre Prompt-Zeile dominant sichtbar (kein "Wo tippe ich?") | 🔧 | `WorkspaceInput.tsx` funktional komplett; **Placeholder auf Englisch**, keine Hero-Eingabe, sekundäre Aktionen in einer Zeile |
| 2.1.2 | Empty State im Chat (Orientierung für Erstnutzer) | ❌ | `ChatStream.tsx` zeigt blank area wenn `messages.length === 0`**kein Welcome/Empty-State** |
| 2.1.3 | "Neuer Chat" sichtbar ohne UDB-Sidebar | ❌ | Nur `+` in `ChatsTab` Toolbar; kein zentraler CTA |
| 2.1.4 | Datei-Drop Entdeckbarkeit | 🔧 | Vollflächen-Drop existiert in `WorkspacePage.tsx`; kein dauerhafter Hinweis im leeren Chat |
| 2.1.5 | DE-Placeholder und i18n | ❌ | Placeholder noch auf Englisch (`Type a message...`) |
### 2.2 Responsive Layout & Breakpoints
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|---|-------------|-----------------|---------------------|
| 2.2.1 | Zwischen-Breakpoint (10251280px): Sidebars auto-einklappen | ❌ | `isMobile` nur bei `≤1024px`; schmale Desktop-Fenster → Mittelspalte zu schmal |
| 2.2.2 | Visuelle Hierarchie Prompt (Schatten/Rand, minHeight) | ❌ | `WorkspaceInput.tsx` ohne besondere Hervorhebung |
| 2.2.3 | Viewport-Testmatrix (1100/1200/1280/1440) | ❌ | Kein Test-Setup dafür |
### 2.3 Vertrauen & Marketing-UI
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|---|-------------|-----------------|---------------------|
| 2.3.1 | Trust-Badges (Daten hosted in der Schweiz, Anbieter/Standort) | ❌ | Login: **kein** Hosting-Hinweis; keine `TrustFooter`/`TrustStrip` Komponente |
| 2.3.2 | "Recommended by" Partner-Strip (Valion, PamoCreate, Swiss AI Association etc.) | ❌ | Keine Partner-Logos/Links |
| 2.3.3 | Swiss ® am Logo | ❌ | Nur im Bildasset, nicht in UI sichtbar (Legal klären) |
| 2.3.4 | Sicherheits-Banner in SourcesTab ("Verbindung ist read-only") | ❌ | `SourcesTab.tsx` ohne Info-Banner |
### 2.4 Billing & Pricing Auffindbarkeit
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|---|-------------|-----------------|---------------------|
| 2.4.1 | Billing-Funktionalität (komplett) | ✅ | `BillingDataView.tsx` mit Tabs, Balance Cards, Transaktionen |
| 2.4.2 | Einstieg Billing nach Login (Teaser/Banner) | ❌ | Kein Dashboard-Teaser; Zugang nur via Nav-Baum + User-Menü |
| 2.4.3 | Balance im UserSection (neben Avatar) | ❌ | Nur Menü-Eintrag "Guthaben" |
| 2.4.4 | Billing-Copy für Nicht-Admins | ❌ | Kein Hinweis "Frag deinen Admin" |
### 2.5 Onboarding & Erstnutzung
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|---|-------------|-----------------|---------------------|
| 2.5.1 | Connector-Onboarding ("sicher verbinden, nichts kaputt") | ❌ | Keine Microcopy in SourcesTab |
| 2.5.2 | Progressive Offenlegung (weniger gleichzeitig auf Startscreens) | ❌ | Workspace zeigt alles parallel |
---
## Teil 3: Infrastruktur & Demo-Vorbereitung
### 3.1 Demo-Konfigurationen
| # | Item | Codebase-Status | Evidenz / Bemerkung |
|---|------|-----------------|---------------------|
| 3.1.1 | Demo-Config-Infrastruktur (Base + Admin API) | ✅ | `_baseDemoConfig.py`, `routeAdminDemoConfig.py` |
| 3.1.2 | Referenz: `investorDemo2026.py` | ✅ | Vollständiges Muster mit Mandant, User, Features, Billing |
| 3.1.3 | Demo-Mandant "Bling Demo" | ❌ | Kein `blingDemo2026.py` |
| 3.1.4 | Demo-Mandant "PWG Demo" | ❌ | Kein `pwgDemo2026.py` |
| 3.1.5 | Demo-Mandant "Quid Demo" | ❌ | Kein `quidDemo2026.py` |
### 3.2 Testdaten
| # | Item | Codebase-Status | Evidenz / Bemerkung |
|---|------|-----------------|---------------------|
| 3.2.1 | Fiktives Mieterdossier (Neutralisierung) | ✅ | `demoData/neutralizer/tenant-dossier.pdf` + Generator |
| 3.2.2 | Knowledge-Base Demo-Dateien | ✅ | `demoData/knowledge-base/` — 4 Dateien |
| 3.2.3 | Budget-Excel (Soll-Werte) | ❌ | Kein `.xlsx` im Repo |
| 3.2.4 | Musterbelege (Rechnung, Spesen, Bank, Versicherung) | ❌ | Keine Demo-Belege |
| 3.2.5 | Quid-Testdaten (CSV: Umsatz, Kunden, Support) | ❌ | Keine kundenspezifischen Testdaten |
| 3.2.6 | Bling-Testdaten (Bexio-kompatibel) | ❌ | Keine Bexio-Testdaten |
| 3.2.7 | PWG-Testdaten (Abacus-kompatibel) | ❌ | Keine Abacus-Testdaten |
### 3.3 Demo-Workflows & Skripte
| # | Item | Codebase-Status | Evidenz / Bemerkung |
|---|------|-----------------|---------------------|
| 3.3.1 | System-Template "Treuhand: PDF-Klassifizierung" | ✅ | In `interfaceBootstrap.py` |
| 3.3.2 | Demo-Workflow (manual trigger → SharePoint → Trustee Pipeline) | ❌ | System-Template existiert, aber kein dedizierter Demo-Workflow |
| 3.3.3 | Demo-Skript Bling | ❌ | |
| 3.3.4 | Demo-Skript PWG | ❌ | |
| 3.3.5 | Demo-Skript Quid | ❌ | |
| 3.3.6 | Neutralisierungs-Demo-Flow (Schritt-für-Schritt) | ❌ | Kein Skript |
---
## Teil 4: Allgemeine Treuhand-Use-Cases (Prozessdokumentation)
Diese Use Cases stammen aus der allgemeinen Treuhand-Prozessdokumentation und sind für **alle** Kunden relevant.
### 4.1 Datenerfassung — Kleine Unternehmen
| # | Anforderung | Codebase-Status |
|---|-------------|-----------------|
| 4.1.1 | Belege sortieren & mit Banktransaktionen referenzieren | 🔧 — Belegverarbeitung vorhanden; kein Bank-Statement-Matching |
| 4.1.2 | Import Banktransaktionen via Excel/CSV | 🔧 — File-Upload + Extraktion vorhanden; kein dedizierter Bank-Import |
| 4.1.3 | Automatisierte Rückfragen an Kunden bei fehlenden Belegen | ❌ |
### 4.2 Lohnbuchhaltung
| # | Anforderung | Codebase-Status |
|---|-------------|-----------------|
| 4.2.1 | Überleitung Lohnaufwand (Fibu vs. Lohnbuchhaltung) | ❌ — Kein Lohn-Feature |
| 4.2.2 | Nicht-lohnwirksame Buchungen identifizieren | ❌ |
| 4.2.3 | Fehlende Lohnmeldungen erkennen | ❌ |
### 4.3 Steuererklärung
| # | Anforderung | Codebase-Status |
|---|-------------|-----------------|
| 4.3.1 | Belege nach Kategorien ordnen | 🔧 — Klassifikation vorhanden |
| 4.3.2 | Steuererklärung erstellen | ❌ — Kein Steuer-Feature |
| 4.3.3 | Vorjahresvergleich und Plausibilisierung | ✅ — In Analyse-Prompts |
### 4.4 Jahresabschluss (Mittlere/Grosse Unternehmen)
| # | Anforderung | Codebase-Status |
|---|-------------|-----------------|
| 4.4.1 | Banksalden abgleichen (Buchhaltung vs. Bank) | 🔧 — Konzeptionell via Agent; kein dedizierter Check |
| 4.4.2 | PayPal, Revolut, ausländische Konten nachbuchen | ❌ |
| 4.4.3 | Wertschriftendepot nachbuchen | ❌ |
| 4.4.4 | Fehlerkonto-Transaktionen bereinigen | ❌ |
| 4.4.5 | Kreditkartenkonto abstimmen | ❌ |
| 4.4.6 | Zahlungsanbieter prüfen (Stripe, Amex) | ❌ |
| 4.4.7 | Nebenbücher mit Fibu abstimmen | ❌ |
| 4.4.8 | Skonto-Differenzen ausbuchen | ❌ |
| 4.4.9 | Konzerninterne Abstimmung | ❌ |
| 4.4.10 | Darlehenskonten abgleichen, Zinsen berechnen | ❌ |
| 4.4.11 | Fremdwährungsbewertung gemäss ESTV | ❌ |
| 4.4.12 | Eigenkapitalveränderungen mit HR abgleichen | ❌ |
| 4.4.13 | Umsatz-/Aufwandsplausibilisierung | ✅ — Im Jahresabschluss-Prompt |
| 4.4.14 | Rechnungsabgrenzungen (aktiv/passiv) | 🔧 — Im Prompt adressiert |
| 4.4.15 | Abschreibungen erfassen | ❌ |
| 4.4.16 | MWST-Jahresabstimmung | ❌ |
| 4.4.17 | Steueraufwand-Rückstellungen berechnen | ❌ |
| 4.4.18 | Bilanz und ER plausibilisieren | ✅ — Im Jahresabschluss-Prompt |
| 4.4.19 | Analyse gesetzliche Bestimmungen (Kapitalverlust, Überschuldung) | ✅ — Im Jahresabschluss-Prompt |
### 4.5 Finanzielle Führung & Controlling
| # | Anforderung | Codebase-Status |
|---|-------------|-----------------|
| 4.5.1 | Businessplan → Absatzplanung → Ertragsplanung | ❌ |
| 4.5.2 | Investitionsplan und Finanzplan | ❌ |
| 4.5.3 | Budget mit Szenarien | 🔧 — Budget-Prompt vorhanden; Szenarien via Chat |
| 4.5.4 | Soll/Ist-Vergleich mit Abweichungsanalyse | ✅ — Budget-Vergleich Prompt-Template |
| 4.5.5 | Deckungsbeitragsrechnung | ❌ |
| 4.5.6 | Projekt-Controlling | ❌ |
| 4.5.7 | Benchmarkanalyse | ❌ |
| 4.5.8 | KPI-Monitoring mit proaktiver Benachrichtigung | 🔧 — KPIs via Agent; kein proaktives Alert-System |
### 4.6 Revisionen
| # | Anforderung | Codebase-Status |
|---|-------------|-----------------|
| 4.6.1 | Ordentliche Revisionen unterstützen | ❌ — Kein Revisions-Feature |
### 4.7 Steueroptimierung & Simulationen
| # | Anforderung | Codebase-Status |
|---|-------------|-----------------|
| 4.7.1 | Jahresrechnung auf steuerliche Probleme prüfen | ❌ |
| 4.7.2 | Simulationen (Lohn vs. Dividende, Umzug, 3. Säule, BVG) | ❌ |
| 4.7.3 | MWST-Prüfung, VST-Korrekturen | ❌ |
| 4.7.4 | Steuerausscheidungen auf verschiedene Kantone | ❌ |
### 4.8 Interdisziplinäre Themen
| # | Anforderung | Codebase-Status |
|---|-------------|-----------------|
| 4.8.1 | Umstrukturierungen | ❌ |
| 4.8.2 | Steuer-/Vorsorgestrategien | ❌ |
| 4.8.3 | Nachfolgeplanung | ❌ |
| 4.8.4 | Unternehmensbewertungen | ❌ |
---
## Zusammenfassung: Status-Überblick
### Fertig (✅) — Kernplattform funktioniert
| Bereich | Was steht |
|---------|-----------|
| **Trustee Agent-Tools** | `refreshTrusteeData`, `aggregateTable`, Connection-Pooling, Result-Caching |
| **Graph-Editor** | Trustee-Kategorie + 4 Nodes, SharePoint-Nodes, Flow-Nodes (Loop, If/Else, Switch, Merge) |
| **Prompt-Templates** | 5 Analyse-Typen (Budget, KPI, Cashflow, Prognose, Jahresabschluss) als Quick Actions + Template Workflows |
| **Accounting-Connectors** | Bexio, Abacus, RunMyAccounts |
| **Belegverarbeitung** | Extraktion → Klassifikation → Kontierung → Sync (end-to-end) |
| **CommCoach** | Feature komplett, 10+ Personas inkl. 4 Immobilien-Personas (PWG), Gamification, Seeding |
| **Neutralisierung** | PII-Masking, Playground, Private-LLM, Mieterdossier-PDF |
| **Multi-Tenancy** | Mandantenisolation, Datentrennung, Rollenwechsel |
| **Billing** | BillingDataView, Balance, Transaktionen, useBilling |
| **SharePoint-Integration** | 6 Workflow-Nodes + Automation |
| **Demo-Infrastruktur** | Base-Config, Admin-API, Investor-Demo als Referenz |
### Teilweise (🔧) — Grundstruktur steht, Erweiterung nötig
| Bereich | Was fehlt |
|---------|-----------|
| Firmen-Mapping Kunden/Lieferanten | Regelbasiertes Matching-UI |
| Beleg-Tagging | Beleg-spezifisches Tag-System |
| Vorsteuer-Automatisierung | MWST-Zuordnung bei Belegverarbeitung |
| Liquiditätsplanung | Dediziertes Prompt-Template |
| Workspace-Prompt | DE-Placeholder, visuelle Hervorhebung |
| Datei-Drop | Hinweis im Empty State |
| Budget-Prompt | Demo-Excel-Datei fehlt |
### Offen (❌) — Noch zu bauen
#### Prio 0: PWG-Pilot (Versand Sommer 2026 — Deadline-gebunden)
| Item | Aufwand | Beschreibung |
|------|---------|-------------|
| Abacus-Testmandant API-Zugang | Extern | Patrick koordiniert mit Abacus; PWG muss Zugriff bestätigen |
| Prompt-Template "Mietzinsbestätigung prüfen" | Mittel | Neues Template: Scan vs. Originaldaten, Status-Klassifikation, Antwortvorschlag |
| Pilot-Workflow im Graph-Editor | Mittel | trigger → sharepoint.listFiles → loop → download → extract → ai.prompt → report → email |
| Abacus-Mietzins-Stammdaten-Abfrage | Klein | Konfiguration im Abacus-Connector für Mietzins-Referenzdaten |
| Demo-Mandant PWG | Mittel | `pwgDemo2026.py` — Trustee (Abacus), CommCoach, Neutralisierung, Workspace |
| PWG Knowledge-Set | Klein | Öffentliche PDFs (Geschäftsberichte, Vermietungsreglement) in Knowledge-Base laden |
| Preismodell / Kalkulation Pilot | Extern | Grundgebühr/User/Monat + Token-Gebühr; basierend auf 4×800 Schreiben/Jahr |
#### Prio 1: Demo-Blocker / Weitere Kunden-Demos
| Item | Aufwand | Beschreibung |
|------|---------|-------------|
| Demo-Mandant Bling | Mittel | `blingDemo2026.py` — Trustee (Bexio), Workspace, Graph-Editor |
| Demo-Mandant Quid | Klein | `quidDemo2026.py` — Workspace, Graph-Editor, CSV-Upload |
| Budget-Excel | Klein | Soll-Werte 2026 für Demo |
| Musterbelege (PDFs) | Klein | 35 Belege (Rechnung, Spesen, Bank, Versicherung) |
| Demo-Skripte | Klein | Schritt-für-Schritt pro Kunde |
| Neutralisierungs-Demo-Flow | Klein | Dokumentation |
| Demo-Workflow Graph-Editor (generisch) | Mittel | trigger.manual → SharePoint → Trustee Pipeline |
#### Prio 2: UI/UX-Verbesserungen (Erstnutzer-Hürde senken)
| Item | Aufwand | Beschreibung |
|------|---------|-------------|
| Empty State ChatStream | Klein | Titel, Bullets, "Neuer Chat" Button |
| DE-Placeholder + i18n | Klein | `WorkspaceInput.tsx` |
| "Neuer Chat" CTA in Mitte | Klein | `WorkspacePage.tsx` |
| Zwischen-Breakpoint (10251280px) | Mittel | Sidebar-Auto-Collapse |
| Trust-Strip/Footer (Login, Landing) | Mittel | Hosting Schweiz, Partner-Logos (Legal nötig) |
| Billing-Teaser nach Login | Klein | Link oder Banner |
| Connector-Onboarding Copy | Klein | Sicherheits-Banner in SourcesTab |
| Balance im UserSection | Klein | Zahl neben Avatar |
#### Prio 3: Feature-Erweiterungen (Roadmap)
| Item | Aufwand | Beschreibung |
|------|---------|-------------|
| Xero-Connector | Gross | Neuer Accounting-Connector |
| FileMaker-Connector (PWG) | Gross | Portfolio, Liegenschaften, Erneuerungsplanung; Datenmenge/-qualität erst prüfen |
| Buchungsregeln für wiederkehrende Belege | Mittel | Regel-Engine |
| Liquiditätsplanungs-Template | Klein | Neues Prompt-Template |
| KPI-Monitoring mit Alerts | Gross | Proaktives Benachrichtigungssystem |
| Template-basierte Dokumentenerstellung (HTML → Word) | Mittel | Erneuerungsstrategien, Corporate Design |
| DB-Change-Detection / Notification-Trigger | Mittel | Reagiert auf Datenbank-Änderungen, triggert Workflows |
| Datenvalidierungs-Workflow | Klein | Erst-Audit: welche Daten korrekt/aktuell |
#### Prio 4: Zurückgestellt (wartet auf externen Input)
| Item | Wartet auf | Kunde |
|------|-----------|-------|
| Gastro-Echtzeit-Integration | Kevin (Bling) soll UC ausformulieren | Bling |
| Zendesk-Connector | Bewusst CSV-Workaround | Quid |
| Regelbasierte Konsolidierung | Lars-Meeting | Quid |
| Grundstücksanalyse (GIS etc.) | Kundenpräzisierung | PWG |
| FileMaker-Integration (PWG) | Datenmenge/-qualität prüfen (PWG + PowerOn) | PWG |
| PWG Datenschutz-/Vertragsklauseln | PWG prüft intern (genossenschaftliche Struktur) | PWG |
#### Langfristig: Allgemeine Treuhand-Automatisierung
Die Use Cases aus Teil 4 (Lohnbuchhaltung, Steuererklärung, detaillierter Jahresabschluss, Revisionen, Steueroptimierung, interdisziplinäre Themen) sind **konzeptionell dokumentiert** aber noch **nicht in der Codebase**. Diese bilden die Langfrist-Roadmap und werden schrittweise über AI-Prompt-Templates und dedizierte Workflows umgesetzt, sobald die Kern-Use-Cases bei den ersten Kunden validiert sind.
---
## Entscheidungen
| Datum | Entscheidung | Begründung |
|-------|-------------|------------|
| 2026-04-07 | Prompt-Templates als Code in `mainTrustee.py` | Wartbar und versioniert statt externe Dateien |
| 2026-04-07 | `refreshTrusteeData` als separate Action | Separation of Concerns: Sync = schreibend, Query = lesend |
| 2026-04-07 | DB-Connection-Pooling statt Connection-per-Call | Grösster Performance-Hebel (~200ms pro Connection) |
| 2026-04-09 | Quid ohne Zendesk-Connector — CSV-Upload | Gleicher Analyse-Mehrwert, viel weniger Aufwand |
| 2026-04-09 | Gastro-UC und Konsolidierung auf Prio 4 | Warten auf Kunden-Input |
| 2026-04-09 | CommCoach-Personas als schnellster Wow-Effekt für PWG | Feature gebaut, nur Persona-Definitionen nötig |
| 2026-04-07 | UI-Enhancements: Fokus Erstnutzer-Hürde | Ohne klare Userführung springen Kunden ab |
| 2026-04-07 | Trust-Badges: kein ISO, sondern "Daten in CH" | Konkreter Nutzen > abstraktes Zertifikat |
| 2026-04-16 | PWG-Pilot = Jahresmietzinsbestätigungen als erster Produktiv-UC | Konkreter, messbarer Business Case (4×800 Schreiben); Deadline Sommer 2026 |
| 2026-04-16 | Workflow-Philosophie PWG: erst manuell testen, dann automatisieren | Agent wird aus manuell getesteten Prozessen erstellt; Workflows für wiederkehrende Aufgaben |
| 2026-04-16 | FileMaker-Integration auf Prio 4 | Datenmenge/-qualität muss erst geprüft werden; kein Blocker für Pilot |
| 2026-04-16 | Abacus-Testmandant als Voraussetzung für Pilot | Patrick koordiniert API-Zugang direkt mit Abacus |
---
## Betroffene Module
- **Gateway:** `features/trustee/` (Prompts, Quick Actions, Connectors), `features/commcoach/` (Personas), `features/neutralization/` (Demo-Config), `features/graphicalEditor/` (Nodes), `serviceCenter/services/serviceAgent/` (Tools, Caching), `demoConfigs/` (neue Configs), `workflows/methods/methodTrustee/` (Actions), `demoData/` (Testdaten)
- **Frontend Nyla:** `WorkspacePage.tsx` (Layout, Breakpoints, Empty State), `WorkspaceInput.tsx` (Prompt, i18n), `ChatStream.tsx` (Empty State), `Login.tsx` (Trust-UI), `UserSection.tsx` (Balance), `SourcesTab.tsx` (Onboarding-Copy), `BillingDataView.tsx` (Discovery)
- **DB-Migration:** Nein
- **Platform/Wiki:** Nach Release `b-reference/` aktualisieren
## Links
- PWG Workshop-Inputs (16.04.2026): `pamocreate/projects/poweron/customer-pwg/20260415-inputs-pwg.txt`
- Originale Kunden-Inputs: `local/notes/demo-tue-use-cases-inputs-customers.md`
- Merged Demo-Plan (ersetzt): `c-work/1-plan/2026-04-demo2-merged-customer-trustee-plan.md`
- UI-Enhancements Plan (ersetzt): `c-work/1-plan/2026-04-porta-ui-enhancements-team-meeting.md`
- Investor-Demo (Referenz): `platform-core/modules/demoConfigs/investorDemo2026.py`
- Frontend-Referenz: `b-reference/ui-nyla/architecture.md`
- Trustee Main (Prompts): `platform-core/modules/features/trustee/mainTrustee.py`
- CommCoach Personas: `platform-core/modules/features/commcoach/serviceCommcoachPersonas.py`
- Neutralisierung: `platform-core/modules/features/neutralization/`
- Graph-Editor Nodes: `platform-core/modules/features/graphicalEditor/nodeDefinitions/`
- Demo-Daten: `platform-core/demoData/`
- UDM-Konzept: `c-work/0-ideas/unified-document-model.md`
## Abschluss
- [ ] Quell-Dokumente als "superseded by this document" markieren
- [ ] b-reference/ aktualisiert nach Umsetzung
- [ ] TOPICS.md aktualisiert
- [ ] Dieses Dokument → `1-plan/` verschieben wenn Umsetzung startet

View file

@ -0,0 +1,291 @@
<!-- status: idea -->
<!-- started: 2026-06-04 -->
<!-- component: gateway | ui-nyla | platform -->
# Architektur: Vom Kundenbedürfnis zur Lösung — generische Workflow-/Solution-Schicht
> **Ebene:** App-/Plattform-Architektur (eine Stufe über den Feature-/Connector-Plänen).
> **Frage, die wir lösen:** Wie erfüllt PORTA *jedes* wiederkehrende Kundenbedürfnis **ohne kundenspezifischen Code** — als konfigurierte Komposition vorhandener Bausteine?
## Vision: Konfigurierte Use Cases statt geschriebener Applikationen
Der eigentliche Paradigmenwechsel hinter diesem Plan:
**Klassische Software ist von gestern.** Bisher löst man ein Geschäftsproblem, indem jemand eine Applikation *schreibt* — pro Problem, pro Kunde, in Wochen/Monaten. Die Software ist das Asset; jede Anpassung kostet Engineering.
**Wir drehen das um: wir *konfigurieren* komplexe Use Cases, statt Applikationen zu schreiben.** Genau das, was eine AI heute schon tut, wenn sie assistiert: Du beschreibst eine *Absicht*, das System *komponiert* vorhandene Fähigkeiten (Tools, Daten, Logik) zu einem Ergebnis — niemand baut dafür eine App. Diese Architektur ist dieses Prinzip, **produktisiert**:
| AI-Assistenz (heute, z. B. Cursor) | PORTA Solution-Schicht |
|---|---|
| Du beschreibst die Absicht | Business-User beschreibt den Use Case (L4) |
| AI plant die Schritte | Workflow-Agent komponiert den Graph (L2/L3) |
| AI nutzt Tools (lesen, schreiben, ausführen) | Graph nutzt Actions/Connectors (L1) |
| Ergebnis: einmalig, im Chat | Ergebnis: **dauerhaft** — konfiguriert, geplant, governt, mandantenfähig, dem Kunden gehörend |
**Was das für Kunden bedeutet — «next level»:**
- **Massgeschneidert ohne Massanzug-Kosten:** der exakte Fall (Plings 5 Stores, ihre Konten-Ranges) ohne bespoke Entwicklung.
- **Tage statt Monate**, Self-Service statt Vendor-Backlog.
- **Grenzkosten eines neuen Use Cases → nahe null:** Konfiguration, nicht Code.
**Zu Ende gedacht (ehrlich, kein Hype):**
- Es verschwindet *nicht* alle Software. Die **Bausteine** (Connectors, Actions, Engine) und einige **tiefe Features** (eigenes Datenmodell/UI, z. B. `lawyer`) bleiben klassisch geschriebene Software. Der Wechsel passiert in der **Mitte**: die vielen massgeschneiderten Einzellösungen, die man bisher pro Kunde gebaut hat, werden zu **Konfiguration**. Engineering wandert nach **unten** (haltbare, wiederverwendbare Primitive) und nach **oben** (AI-gestützte Konfiguration) — und verschwindet aus der teuren Mitte. Das ist exakt die Feature-vs-Solution-Grenze.
- **Vertrauen ist Voraussetzung, kein Nachgedanke.** Wenn AI/Konfiguration komponiert, braucht es Leitplanken — typisierte Actions, Neutralisierung, Review-vor-Aktivierung, Testlauf ohne Versand. Im Treuhand-/Finanzkontext ist das Pflicht. PORTA hat diese Leitplanken bereits — das macht «konfigurieren statt coden» hier *seriös* möglich.
- **Der Moat** ist nicht ein einzelnes Feature, sondern die **Toolbox + Kompositions-Engine + die AI, die Absicht → Komposition** übersetzt.
**In einem Satz:** PORTA verkauft künftig nicht «eine App», sondern die **Fähigkeit, jeden wiederkehrenden Geschäfts-Use-Case zu konfigurieren** — der konfigurierte Use Case ist das Asset, nicht der handgeschriebene Code.
## Beschreibung und Kontext
Viele Kunden (v. a. im Feature **Trustee**) haben **dasselbe Grundmuster** an Bedürfnissen. Die Kern-Logik:
> Ein Kunde hat kein «Workflow-Problem», sondern ein **Bedürfnis**. Dieses Bedürfnis lässt sich als **Use Case** formulieren, daraus wird — AI-gestützt — ein **Workflow** aus vorhandenen Bausteinen komponiert, **einmal konfiguriert**, **getriggert** (manuell oder per Zeitplan) und dessen **Ergebnis angesehen**. Drumherum braucht es eine **Verwaltung**, mit der ein Business-User genau das selbst tut — ohne dass wir pro Kunde Code schreiben.
Konkrete Bedürfnisse, immer dieselbe Logik:
- Zwei Systeme synchronisieren, einmal einstellen, täglich um 06:00 via Scheduler (Solution S1, → `0-ideas/2026-06-CustomerCases-step3-solutions-plan.md`).
- **Monatsreporting über mehrere Buchhaltungen** (Pling «Kaffee-Klatsch»): am 15. des Monats aus 5 RMA-Buchhaltungen konsolidieren, 6 PDF-Reports erzeugen, **rollenbasiert** per Mail verteilen (Solution S2, → `0-ideas/2026-06-CustomerCases-step3-solutions-plan.md`; Spec: `pamocreate/projects/poweron/customer-pling/20-spezifikation/20260522-workflow-spec-kaffee-klatsch.md` + Anhang).
- Gescannte Jahresmietzinsbestätigungen verarbeiten + Antwortvorschläge (PWG-Pilot, Solution S3, → `0-ideas/2026-06-CustomerCases-step3-solutions-plan.md`).
- Mandatsvorbereitung + Dashboards (Feature, → `0-ideas/2026-06-CustomerCases-step3-features-plan.md`, B1).
**Beobachtung:** Alle vier Beispiele sind **Instanzen desselben Musters**: ein Bedürfnis wird durch eine **Komposition vorhandener Bausteine** (Connectors, Actions/Nodes, AI, Neutralisierung, Dashboards) erfüllt — nicht durch neuen, kundenspezifischen Code. Die Bausteine existieren bereits (Action Library, Graphical Editor, Scheduler, Templates, Connectors, Toolbox). **Was fehlt, ist die Schicht darüber:** eine generische, **kundentaugliche** Oberfläche, mit der ein Business-User (kein Techniker) eigene Workflows **anlegen lässt (AI), konfiguriert, testet, ausführt, ansieht und verwaltet**.
Business-Treiber:
- Skaliert ohne Engineering pro Kunde/Workflow (das eigentliche Plattform-Versprechen).
- Verwandelt jedes Kunden-«Bedürfnis» in ein Self-Service-Produkt → kürzeres Onboarding, höhere Marge.
- Macht die bereits gebauten Bausteine endlich für Endkunden zugänglich (heute nur über den technischen Editor).
## Fokus und kritische Details
- **Das Problem ist NICHT «noch ein Feature», sondern eine fehlende Produkt-Schicht.** Wir bauen kein viertes Buchhaltungs-Detail, sondern die generische **Lifecycle-Verwaltung** für kundeneigene Workflows.
- **Trennung Baustein ↔ Kundenlogik ist Plattform-Gesetz** (gilt schon für Connectors): Bausteine = Code; konkrete Kundenlösung = **Daten** (Graph + Settings + Trigger + Output-Bindung).
- **«Settings in den Notes» ist die falsche Abkürzung.** Einstellungen in Freitext-Notes abzulegen ist verlockend, aber ein Hack. Architektonisch braucht es ein **strukturiertes, validiertes Settings-Modell** pro Workflow (typisiert, versioniert).
- **Feature vs. Solution — die wichtigste Grenze.** Nicht jedes Bedürfnis rechtfertigt ein Code-Feature (wie `lawyer`). Default ist eine **konfigurierte Solution** (Template + Settings). Ein Code-Feature nur, wenn eigene Datenmodelle / tiefe opinionated UI / Domänenlogik nötig sind, die der Graph nicht ausdrücken kann (siehe Entscheidungstabelle).
- **Zwei Personas, zwei Oberflächen:** Der **Graphical Editor** bleibt das technische Authoring-Tool (n8n-Stil). Neu kommt eine **Business-Oberfläche** (Lösungen verwalten), die den Graph *kapselt*. Sie ist die Antwort auf «wo stelle ich meine Sachen ein?».
- **Fragile/relevante Stellen:** `AutoWorkflow/AutoVersion/AutoRun` (Greenfield-DB `poweron_graphicaleditor`), Scheduler (`mainScheduler.py`), Template-Scopes (`user|instance|mandate|system`), Action-Catalog (`/api/automation2/catalog`), Workflow-Agent-Toolbox (`workflow`-Tools: `addNode`, `bindNodeParameter`, …). Wir bauen **auf** diesen, nicht daneben.
## Ziel und Nicht-Ziele
- **Ziel:** Ein generisches **Solution-Konzept** definieren: «konfigurierte, getriggerte, kundentaugliche Verpackung eines Workflows», mit Settings-Schema, Trigger-Policy und Output-/Dashboard-Bindung — als **Daten pro Feature-Instanz**.
- **Ziel:** Eine **kundenseitige Verwaltungs-Oberfläche** (Lifecycle: anlegen → konfigurieren → testen → aktivieren → ausführen → ansehen → verwalten), zuerst im Feature Trustee, dann feature-übergreifend wiederverwendbar.
- **Ziel:** **AI-gestützte Erzeugung** «Use Case → Workflow» über den bestehenden Workflow-Agent.
- **Ziel:** Ein **Use-Case-Katalog** (kuratierte System-Templates) als Startpunkt für die häufigsten Bedürfnisse.
- **Ziel:** Architektur so, dass die vier Beispiele sauber als Spezialfälle abbildbar sind (Validierung unten).
- **Explizit NICHT:** kundenspezifischer Code pro Workflow.
- **Explizit NICHT:** den Graphical Editor ersetzen — wir kapseln ihn.
- **Explizit NICHT:** Settings in Notes/Freitext.
- **Explizit NICHT (jetzt):** Marktplatz/Sharing zwischen Mandanten, Billing-Redesign — später.
## Das wiederkehrende Muster (Kern der Architektur)
Jedes Kundenbedürfnis hat dieselbe Form:
```
BEDÜRFNIS ──(als Use Case formuliert)──► WORKFLOW (Komposition von Bausteinen)
┌───────────────┬───────────────┬────┴────────┬──────────────┐
SETTINGS TRIGGER DATENQUELLEN AI/LOGIK OUTPUT/VIEW
(einmal einst.) (manuell/Zeit/ (Connectors; (Nodes/ (Dashboard/
Event/Form) eigener Plan) Agent) Report/Mail/Tabelle)
```
Beispiele auf dieselbe Form gebracht:
| Bedürfnis | Trigger | Bausteine (Nodes) | Settings | Output |
|---|---|---|---|---|
| 2 Systeme synchronisieren | `trigger.schedule` 06:00 | source-connector → `mapAccounts` → target-connector | Quelle/Ziel, Mapping | Sync-Log/Status |
| **Monatsreporting 5 Buchhaltungen (Pling)** | `trigger.schedule` 15./06:00 + `trigger.manual` (rollen-beschränkt) | `loop`(5 Instanzen) → `refreshAccountingData``queryData`(Salden akt.+VJ) → `data.consolidate``ai.generateDocument`×6 → `rbac.queryUsersByRole``outlook.send``file.create` | Perioden, Konten-Ranges, Empfänger-Rollen, Cron, Branding | 6 PDFs + Mails + Lauf-Protokoll |
| Mietzinsbestätigungen (PWG) | `trigger.schedule` | `sharepoint.listFiles``loop``extractFromFiles``ai.prompt``data.write``email.send` | Ordner, Abacus-Mandant, Empfänger | Übersichtstabelle + Mail |
| Matter Preparation (Lawyer) | `trigger.manual/form` | `lawyer.prepareMatter` (Agent über Quellen) | Lookback, Quellen | Briefing + Dashboards |
**90 % des Kundenwerts ist Komposition, nicht Code.** Die Bausteine sind da. Die **Verpackung + Verwaltung** fehlt.
### Was der Pling-Fall zusätzlich schärft
Der Pling-«Kaffee-Klatsch»-Fall (vollständig spezifiziert inkl. Graph, Configs, Build-Items) zeigt zwei Verfeinerungen, die das Schema bestätigen statt es zu brechen:
1. **Eine Solution kann über mehrere Feature-Instanzen fan-out-en.** Ein Mandant hat hier **5 Trustee-Instanzen** (1 pro Store); die Solution läuft per `flow.loop` über alle. → Solution-**Scope** ist nicht zwingend «1 Instanz», sondern «ein Set von Instanzen eines Mandanten». Das Settings-Modell muss eine Instanz-Auswahl tragen.
2. **Die «Kundenspezifika» sind durchweg Daten — die Lücken sind generische Bausteine.** Was Pling besonders macht (5 Stores, Konten-Ranges 30003999/60006299/50005099, Empfänger, Cron), ist **Settings**. Was im Code fehlt, sind **zwei generische Plattform-Bausteine**, kein Kunden-Code:
- `rbac.queryUsersByRole`**rollenbasierte Empfänger-Auflösung** (Verteiler aus Trustee-Rollen statt gepflegter Listen). Wiederverwendbar für jedes Report-/Notification-Bedürfnis.
- **Trigger-Zugriffskontrolle** (`accessControl.requiredRoles` im `triggerExecutor`) — damit nur z. B. `trustee-admin` den manuellen Lauf auslösen darf.
Genau diese Trennung ist die Architektur-These: *Kundenspezifika → Settings/Graph (Daten); was fehlt → generische L1/L2-Bausteine.*
Weitere wiederverwendbare Muster aus dem Fall: **Konsolidierung** mehrerer Instanzen (`data.consolidate` sumByKey), **selektive Neutralisierung** (nur Namen/Beschreibungen pseudonymisiert, Zahlen/Konten lesbar), **Teil-Resultat-Toleranz** (unvollständige Buchhaltung → durchlaufen mit Markierung, steuerbar per Settings-Flag `stopOnIncomplete`), **Archivierung** der Outputs als `TrusteeDocument`.
## Schichten-Modell (Zielarchitektur)
```
┌───────────────────────────────────────────────────────────────────────────┐
│ L4 SOLUTION SURFACE (kundentaugliche UX, pro Feature-Seite) NEU │
│ «Lösungen»: Katalog · Anlegen(AI) · Settings · Test · Runs · View │
├───────────────────────────────────────────────────────────────────────────┤
│ L3 SOLUTION DEFINITION (Use Case → konfigurierter Workflow) NEU │
│ Solution = Template/Version + Settings-Schema + Trigger-Policy + Output │
│ Use-Case-Katalog · AI-Generierung · strukturierte Settings (kein Notes) │
├───────────────────────────────────────────────────────────────────────────┤
│ L2 COMPOSITION (Graph) VORHANDEN │
│ AutoWorkflow/Version/Run · Graphical Editor · Templates (scopes) │
├───────────────────────────────────────────────────────────────────────────┤
│ L1 PLATTFORM-TOOLBOX (Bausteine) VORHANDEN │
│ Connectors/Datenquellen · Action Library (Methods/Actions=Nodes) · │
│ AI/Agent+Toolbox · Neutralisierung · Knowledge/RAG · Scheduler · │
│ Dashboards-Primitive · RBAC · Multi-Tenancy │
└───────────────────────────────────────────────────────────────────────────┘
```
**L1/L2 existieren** (siehe `b-reference/platform-core/workflow.md`, `automation.md`). **L3/L4 sind neu** und der eigentliche Gegenstand dieses Dokuments.
### L3 — Solution Definition (das neue Kern-Konzept)
Eine **Solution** ist die kundentaugliche Verpackung eines Workflows:
| Bestandteil | Inhalt | Baut auf |
|---|---|---|
| **Workflow-Bindung** | Referenz auf `AutoWorkflow` + `PUBLISHED` `AutoVersion` | vorhanden |
| **Settings-Schema** | typisierte, validierte Parameter, die der Kunde einstellen darf (z. B. «SharePoint-Ordner», «Empfänger», «Periode», «Konten-Mapping») | `FrontendType`/Typed-Action-System, `trigger.form`-Schema |
| **Settings-Werte** | konkrete Belegung pro Solution (inkl. **Instanz-Auswahl** bei Multi-Instanz-Fan-out, z. B. Pling 5 Stores) | neu (Record) |
| **Trigger-Policy** | manuell / Zeitplan / Event / Form, inkl. **Zugriffskontrolle** (welche Rolle darf manuell auslösen) | Scheduler + Trigger-Nodes (+ `accessControl`) |
| **Output-/View-Bindung** | was der Kunde nach dem Lauf sieht — `kind: file \| table \| summary` (Dashboard später); siehe «Output-Bindung — Empfehlung» | `file.create`/Datenraum, FormGenerator/Data-Tables, `AutoRun`/`AutoStepLog` |
| **Katalog-Herkunft** | aus Use-Case-Template instanziiert ODER per AI generiert | System-Templates + Workflow-Agent |
**Designentscheidung (bestätigt 2026-06-04):** Solution **nicht** als grosse neue Parallel-Welt bauen, sondern als **dünne Erweiterung** auf `AutoWorkflow` (Settings-Schema + Presentation-Binding + «is customer-facing»-Flag) plus einen **Settings-Record**. Das hält eine einzige Workflow-Wahrheit (Scheduler, Runs, Versioning greifen unverändert).
**Settings statt Notes:** Das Settings-Schema wird aus dem Graphen abgeleitet (Trigger-Form / als «exposed» markierte Node-Parameter) und/oder kuratiert. Validierung + Verschlüsselung (für Secrets) wie bei Connector-Configs. Das ist die saubere, wartbare Alternative zu Einstellungen in Freitext-Notes.
### L4 — Solution Surface (kundentaugliche UX)
Eine **Seite pro Feature** (Start: Trustee), Name «**Lösungen**», mit dem Lifecycle:
```
[Katalog/Neu] [Meine Lösungen] [Detail einer Lösung]
├─ Use-Case wählen ├─ Liste (aktiv/inaktiv) ├─ Settings (Formular)
├─ oder beschreiben (AI) ├─ Status letzter Lauf ├─ Test / Probelauf
└─ → erzeugt Workflow ├─ nächster geplanter Lauf ├─ Aktivieren + Zeitplan
└─ Run-Historie ├─ Run-Trace (lesbar)
├─ Output/Dashboard
└─ «Im Editor öffnen» (Advanced)
```
- **UI-Struktur (Antwort auf Frage 1):** **Eine** Seite «Lösungen» pro Feature — *kein* Seiten-Wildwuchs und keine Aufblähung der technischen Automation-UI. Diese eine Seite hat **Unteransichten** (Liste · Katalog/Neu · Detail) und das **Detail hat Tabs**: *Einstellungen · Testlauf · Läufe · Ausgabe*.
- Business-User bleibt in L4; «Im Editor öffnen» ist die **Escape-Hatch** nach L2 für Power-User/uns.
- Wiederverwendung: Run-Historie/Trace existiert (`AutoRun`/`AutoStepLog`, SSE `runs/{runId}/stream`); wir rendern es nur **kundentauglich** statt technisch.
- Verknüpfung zum Datenquellen-Plan: «Datenquellen» (Connectors) ist eine Schwester-Seite; «Lösungen» nutzt die dort konfigurierten Quellen.
### AI: Use Case → Workflow
Der bestehende **Workflow-Agent** (Toolbox `workflow`: `readWorkflowGraph`, `addNode`, `bindNodeParameter`, `listUpstreamPaths`, …) ist bereits der Mechanismus, um aus einer Beschreibung einen Graphen zu bauen/ändern. L3 stellt ihm:
1. den **Use-Case-Text** des Kunden,
2. den **Action-Catalog** (verfügbare Bausteine, `/api/automation2/catalog`),
3. die **konfigurierten Datenquellen** der Instanz,
bereit und lässt ihn einen Graphen erzeugen → als Draft-Version speichern → der Kunde konfiguriert nur noch die Settings. Kuratierte **System-Templates** decken die häufigsten Fälle deterministisch ab (kein AI-Risiko); AI nur für Neues/Abweichendes, **mit Review-/Freigabe-Schritt vor Aktivierung**.
## Feature vs. Solution — die Architektur-Entscheidung
| Kriterium | → **Solution** (Daten/Config) | → **Feature** (Code) |
|---|---|---|
| Eigene Datenmodelle nötig? | nein (nutzt bestehende) | ja (z. B. `LawyerMatter`) |
| Tiefe, opinionated UI? | nein (generische Solution-UX) | ja (z. B. Matter-Preparation-View) |
| Aus Bausteinen komponierbar? | ja | nein (Domänenlogik) |
| Time-to-value | Tage | Wochen |
| Beispiel | SelectLine→RMA-Sync, Monatsbericht, PWG-Pilot | `lawyer`, `commcoach`, `trustee` selbst |
**Leitsatz:** *Solution-first.* Ein Code-Feature wird nur gebaut, wenn die Solution-Schicht es nachweislich nicht trägt. So bleibt die Plattform schlank und die «keine Kundenlogik im Code»-Regel real.
## Validierung an den Beispielen
| Beispiel | Abbildung in dieser Architektur |
|---|---|
| **Umsystem-Integration** (SelectLine→RMA) | L1: SelectLine/RMA-Connectors · L2: Import-Graph · L3: Solution «Systeme synchronisieren» (Settings: Quelle/Ziel/Mapping/Zeitplan) · L4: erscheint unter «Lösungen» neben «Datenquellen» |
| **Pling Kaffee-Klatsch** (Monatsreporting) | L1: 5× RMA-Connector, Outlook, `data.consolidate`, `ai.generateDocument` · L2: Fan-out-Graph (`loop` über 5 Instanzen, Konsolidierung, 2 Report-Loops, Verteilung) · L3: Solution mit Settings (5 Instanzen, Konten-Ranges, Cron, Empfänger-Rollen, `stopOnIncomplete`) + Output (6 PDFs, archiviert) · L4: «Jetzt ausführen» (rollen-beschränkt), Run-Historie, Status. **Deckt 2 generische Bausteinlücken auf** (`rbac.queryUsersByRole`, Trigger-`accessControl`) — kein Kunden-Code. |
| **PWG-Pilot** (Mietzinsbestätigungen) | L1: SharePoint/Abacus/Email/extract/ai · L2: 7-Schritt-Graph · L3: Solution mit Settings (Ordner, Mandant, Empfänger) + Output-Tabelle · L4: Test/Aktivieren/Run-Historie |
| **Lawyer-Feature** | Mischfall: **Feature** (eigene Modelle + opinionated UI) **plus** Solutions darin (Matter-Prep, Dashboard-Refresh). Bestätigt die Feature-vs-Solution-Grenze. |
→ Alle vier passen ohne Architektur-Bruch. Das Muster trägt. Der Pling-Fall ist der **stärkste Beleg**: vollständig spezifiziert, ~2 Wochen Build, fast ausschliesslich vorhandene Bausteine — und die einzigen Code-Lücken sind **generisch**, nicht kundenspezifisch.
## Betroffene Module (Skizze)
- **Gateway:**
- `features/graphicalEditor/``AutoWorkflow` um Settings-Schema + Presentation-Binding + `customerFacing`-Flag erweitern; Settings-Record-Modell. **DB-Migration: ja (Greenfield, additiv).**
- `workflows/scheduler/mainScheduler.py` — unverändert nutzbar (Trigger-Policy mappt auf bestehende Schedule-Logik).
- `interfaces/interfaceBootstrap.py` — Use-Case-Katalog als System-Templates.
- `serviceCenter/services/serviceAgent/` (Toolbox `workflow`) — Use-Case→Graph-Generierung; ggf. Prompt/Guardrails ergänzen.
- Solution-Routes (CRUD Settings, Test-Run, Activate) — dünn über bestehende Editor-/Run-Routes.
- **Generische Bausteine aus dem Pling-Fall** (wiederverwendbar, kein Kunden-Code): neue Action `rbac.queryUsersByRole` (rollenbasierte Empfänger-Auflösung) und `triggerExecutor`-Erweiterung um `accessControl.requiredRoles` (Rollen-Check beim manuellen Trigger).
- **Testlauf-Modus:** run-level `testMode` im Run-Context; kommunikations-/seiteneffekt-Actions (Mail/Outlook/Teams/Webhook) prüfen das Flag und unterdrücken den ausgehenden Versand (loggen «würde senden an …»). Reports/Dateien werden trotzdem erzeugt (siehe Frage 7).
- Solution-Scope: Settings müssen ein **Set von Feature-Instanzen** referenzieren können (Multi-Instanz-Fan-out, z. B. 5 Stores).
- **Frontend (ui-nyla):**
- Neue generische **`SolutionsView`** (Katalog · Liste · Detail mit Settings-Formular · Test · Runs · Output), als Feature-Seite registriert (analog `FeatureView.tsx` VIEW_COMPONENTS + UI-Areas in `main<Feature>.py`).
- Settings-Formular-Renderer aus dem Settings-Schema (FrontendType-getrieben).
- **DB-Migration:** ja (additiv auf Greenfield-DB).
- **Andere:** RBAC (neue UI-Area, customer-facing Rollen), Neutralisierung (unverändert über Services), Billing (Run-Volumen).
## Entscheidungen (Vorschläge — zu bestätigen)
| Datum | Entscheidung | Begründung |
|-------|-------------|------------|
| 2026-06-04 | Neue **Solution-Schicht (L3/L4)** statt neues Feature pro Bedürfnis | Skaliert ohne Code pro Kunde |
| 2026-06-04 | Solution = **dünne Erweiterung von `AutoWorkflow`** + Settings-Record (keine Parallel-Welt) | Eine Workflow-Wahrheit; Scheduler/Runs/Versioning unverändert |
| 2026-06-04 | **Strukturierte Settings** statt Notes | Validierbar, versioniert, sicher (Secrets) |
| 2026-06-04 | **Solution-first**, Feature nur bei eigenem Datenmodell/Tiefe | «keine Kundenlogik im Code» real halten |
| 2026-06-04 | Start im Feature **Trustee**, Schicht aber **feature-übergreifend** designen | breiteste Wiederverwendung |
| 2026-06-04 | Solution-Scope = **Set von Feature-Instanzen** (nicht nur eine) | Pling-Fan-out (5 Stores) bricht sonst das Modell |
| 2026-06-04 | Rollenbasierte Verteilung als **generischer Baustein** (`rbac.queryUsersByRole`) | aus Pling abgeleitet, wiederverwendbar für jedes Report-/Notification-Bedürfnis |
| 2026-06-04 | UI = **eine «Lösungen»-Seite pro Feature** mit Unteransichten (Liste/Detail) + Tabs im Detail | kein Seiten-Wildwuchs; Technik-UI bleibt unangetastet (Frage 1) |
| 2026-06-04 | Settings-Schema **automatisch abgeleitet** (aus `trigger.form`/exposed Params) | minimaler Pflegeaufwand; Overrides später (Frage 2) |
| 2026-06-04 | **AI-Generierung ja** — Templates deterministisch, AI nur für Neues + Review vor Aktivierung | Geschwindigkeit ohne Kontrollverlust (Frage 3) |
| 2026-06-04 | RBAC: **bestehende Feature-Rollen** nutzen, keine neuen customer-facing Rollen | weniger Komplexität; konsistent zu Feature (Frage 5) |
| 2026-06-04 | Naming: **«Lösungen»** (engl. *Solutions*) | bestätigt (Frage 6) |
| 2026-06-04 | Testlauf = **realer Lauf mit `testMode`** (Kommunikation unterdrückt, Artefakte erzeugt) | echtes Verhalten testen, ohne ungewollte Mails (Frage 7) |
| 2026-06-04 | Output-Bindung **gestuft** (`file`/`table`/`summary` jetzt, `dashboard` später) | nutzt Vorhandenes; keine BI-Engine bauen (Frage 4 — Detail offen) |
## Beantwortete Fragen (Entscheid 2026-06-04)
1. **Daten-Heimat:****`AutoWorkflow` erweitern** (kein eigenes Solution-Modell).
*UI-Konsequenz (deine Frage):* Die Backend-Erweiterung berührt die technische Automation-UI (Graphical Editor / Ops) **nicht** — es entstehen **nicht** «viele Automation-Seiten». Stattdessen **eine** neue kundentaugliche Seite **«Lösungen» pro Feature**, die denselben `AutoWorkflow` nur anders *präsentiert*. Aufbau: **Liste** (aktiv/inaktiv, letzter/nächster Lauf) · **Katalog/Neu** (Vorlage oder AI) · **Detail mit Tabs** (*Einstellungen · Testlauf · Läufe · Ausgabe*). Also: **eine Seite pro Feature, Unteransichten + Tabs im Detail** — siehe Mockup.
2. **Settings-Schema-Quelle:****Automatisch abgeleitet** aus `trigger.form` + als «exposed» markierten Node-Parametern. (Kuratierte Overrides bei Bedarf später.)
3. **AI-Generierung:****Ja.** Katalog-Templates deterministisch; AI nur für Neues, mit Review-/Freigabe-Schritt vor Aktivierung.
4. **Output/Dashboard:** ⚠️ **Richtung entschieden, Detail offen — Empfehlung im nächsten Abschnitt.**
5. **RBAC:****Bestehende Feature-Rollen** (z. B. `trustee-admin` anlegen/aktivieren/manuell starten; `trustee-*` ansehen). Keine neuen customer-facing Rollen.
6. **Naming:****«Lösungen»** (engl. *Solutions*).
7. **Test/Probelauf:****Realer Lauf, Kommunikation blockierbar.** Der Testlauf läuft echt (echte Daten/Bausteine), nur **ausgehende Kommunikation wird unterdrückt** via run-level **`testMode`**: Mail/Outlook/Teams/Webhook-Actions prüfen das Flag und senden nicht (loggen «würde senden an …»). Reports/Dateien entstehen trotzdem. Sauberer als ein vollständig isolierter Mock-Run.
## Output-Bindung — Empfehlung (Frage 4)
Der schwierigste Punkt, weil «Output» von «PDF im Mail-Anhang» bis «interaktives Dashboard» reicht. **Empfehlung: gestuft, kleinster tragfähiger Kern zuerst — keine generische Dashboard-Engine bauen.** Eine Solution deklariert eine `outputBinding` mit einem `kind`:
| `kind` | Was der Kunde sieht | Baut auf (vorhanden) | deckt ab |
|---|---|---|---|
| `file` | Liste erzeugter Dokumente (PDF/XLSX), Öffnen/Download | `file.create``TrusteeDocument` / Datenraum | Pling, SelectLine-Log |
| `table` | Ergebnis-Tabelle (sortier-/filterbar) | FormGenerator / Data-Tables (`queryData`) | PWG-Übersicht |
| `summary` | Status/Kennzahlen + Lauf-Protokoll | `AutoRun`/`AutoStepLog` (Run-Trace) | jeder Sync/Lauf |
| `none` | nur Lauf-Status | — | reine Mail-Workflows |
- **Jetzt bauen:** `file`, `table`, `summary` — alle nutzen Vorhandenes, kein neuer Renderer-Stack. Deckt alle vier Cases ab.
- **Später:** Rich-Dashboards über die **bestehende AI-Report-/Canvas-Pipeline** wiederverwenden (`kind: dashboard`), nicht neu erfinden.
- **Abgrenzung (wichtig):** Braucht ein Kunde eine **tiefe, opinionated Dashboard-UI**, ist das das Signal für ein **Feature** (Code), nicht für eine Solution. Die Output-Bindung bleibt bewusst schlank — sie *zeigt* Ergebnisse, sie ist keine BI-Engine.
- **Detail beim Bauen (offen):** genaues `outputBinding`-Schema (wie referenzieren wir das Artefakt — Run-Output-Key vs. Document-Query) und ob `table`-Spalten frei konfigurierbar sind oder aus dem Node-Output abgeleitet werden. *Vorschlag:* aus Node-Output ableiten (konsistent zu Frage 2).
## Meine Gedanken / Empfehlung
- **Das ist kein Feature, das ist *die* Produktisierung der Plattform.** Bisher ist PORTA ein Werkzeugkasten mit zwei Enden (technischer Editor + Ops-Dashboard). Die fehlende Mitte — eine kundentaugliche **Solution-Schicht** — ist der Hebel, der aus «wir bauen pro Kunde» ein skalierendes SaaS macht.
- **Nichts Neues erfinden, verpacken.** Alle Bausteine (Graph, Templates, Scheduler, Agent, Connectors) sind da. Der Aufwand liegt in **L3 (Settings/Trigger/Output als Daten)** und **L4 (eine gute, einfache UX)** — nicht in neuer Engine.
- **Die wichtigste Disziplin ist die Feature-vs-Solution-Grenze.** Ohne sie bauen wir wieder pro Kunde ein Feature (siehe die Klassifikationstabelle im `CustomerCases-step3-solutions-plan`). Mit ihr wird der Default «konfigurieren statt coden».
- **Settings strukturieren, nicht in Notes.** Das ist die kleine Entscheidung mit grosser Wirkung: sie macht Solutions wartbar, sicher und versionierbar.
- **Pling als idealer erster realer Beleg.** Der Fall ist bereits voll spezifiziert (~2 Wochen Build) und braucht nur zwei *generische* Ergänzungen (`rbac.queryUsersByRole`, Trigger-`accessControl`). Er beweist die These am konkreten Geld-Use-Case und liefert nebenbei wiederverwendbare Bausteine.
- **Inkrementeller erster Schnitt:** (1) `AutoWorkflow` um Settings-Schema + `customerFacing` + Instanz-Set erweitern; (2) 12 kuratierte System-Templates (z. B. «Systeme synchronisieren» und «Periodisches Reporting» aus Pling); (3) minimale `SolutionsView` (Liste + Settings + Test + Aktivieren + Run-Historie) im Trustee. Damit ist das Muster end-to-end belegt — demonstrierbar am SelectLine→RMA- **und** am Pling-Fall.
- **Verhältnis zu den anderen Plänen:** Der Umsystem-/Datenquellen-Plan liefert **L1-Connectors**; dieser Plan liefert **L3/L4**. Lawyer ist ein **Feature**, das L1L4 konsumiert. Drei Pläne, eine Architektur.
## Links
- Beispiel Reporting/Fan-out (Pling): `pamocreate/projects/poweron/customer-pling/20-spezifikation/20260522-workflow-spec-kaffee-klatsch.md` (+ `-anhang.md`)
- Umsetzungsplan Solutions (alle konfigurierten Use Cases): `c-work/0-ideas/2026-06-CustomerCases-step3-solutions-plan.md`
- Umsetzungsplan Features & Bausteine (der Code dahinter): `c-work/0-ideas/2026-06-CustomerCases-step3-features-plan.md`
- Kommunikation: Product Summary `c-work/0-ideas/2026-06-CustomerCases-step2-communication-product-summary.md` (+ `.pdf`), Mockup `c-work/0-ideas/2026-06-CustomerCases-step2-communication-mockup.html`
- Bausteine: `b-reference/platform-core/workflow.md`, `b-reference/platform-core/automation.md`
- Datenquellen-Trennung: `b-reference/platform/unified-data-bar.md`
## Abschluss
- [x] Offene Fragen beantwortet (Entscheid 2026-06-04); Detail Output-Bindung beim Bauen
- [ ] Bei Annahme → Plan-Dokument in `c-work/1-plan/` (erster Schnitt, Trustee)
- [ ] `b-reference/` Kanon-Seite «Solutions / Customer Workflows» nach Umsetzung
- [ ] `TOPICS.md` Eintrag

View file

@ -0,0 +1,762 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>PORTA · Lösungen (Solution-Schicht Mockup)</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:opsz,wght@9..40,400;9..40,500;9..40,600;9..40,700&display=swap" rel="stylesheet" />
<style>
:root {
--color-bg: #F8F9FA;
--bg-primary: #ffffff;
--bg-secondary: #F7FAFC;
--bg-dark: #EDF2F7;
--surface-color: #F7FAFC;
--text-primary: #1A202C;
--text-secondary: #4A5568;
--text-tertiary: #718096;
--border-color: #E2E8F0;
--border-dark: #CBD5E0;
--primary-color: #4A6FA5;
--primary-color-dark: #3D5D8A;
--primary-light: rgba(74, 111, 165, 0.1);
--primary-color-light: rgba(74, 111, 165, 0.15);
--success: #38A169;
--success-bg: #C6F6D5;
--warning: #D69E2E;
--warning-bg: #FAF089;
--error: #C53030;
--error-bg: #FED7D7;
--gray: #718096;
--radius-lg: 10px;
--radius-md: 8px;
--radius-sm: 6px;
--font: "DM Sans", system-ui, -apple-system, sans-serif;
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; height: 100%; }
body {
font-family: var(--font);
background: var(--bg-primary);
color: var(--text-primary);
font-size: 14px;
-webkit-font-smoothing: antialiased;
}
/* ===== App shell ===== */
.app { display: flex; height: 100vh; overflow: hidden; }
.sidebar {
width: 280px; min-width: 280px; height: 100%;
background: var(--surface-color);
border-right: 1px solid var(--border-color);
display: flex; flex-direction: column;
}
.logo {
display: flex; align-items: center; gap: 8px;
padding: 20px 18px; border-bottom: 1px solid var(--border-color);
font-size: 22px; font-weight: 700; letter-spacing: -0.02em;
}
.logo .dot { width: 28px; height: 28px; border-radius: 8px; background: linear-gradient(135deg, var(--primary-color), var(--primary-color-dark)); display:flex; align-items:center; justify-content:center; color:#fff; font-size:15px; }
.logo .pow { color: var(--text-primary); }
.logo .on { color: var(--primary-color); }
.nav { flex: 1; overflow-y: auto; padding: 12px 10px; }
.nav .group { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-tertiary); padding: 14px 10px 6px; }
.nav a {
display: flex; align-items: center; gap: 10px;
padding: 9px 12px; border-radius: var(--radius-sm);
color: var(--text-secondary); text-decoration: none; font-weight: 500;
margin: 1px 0; cursor: pointer; font-size: 13.5px;
}
.nav a:hover { background: rgba(0,0,0,0.03); color: var(--text-primary); }
.nav a.active { background: var(--primary-light); color: var(--primary-color-dark); font-weight: 600; }
.nav a .ic { width: 18px; text-align: center; opacity: 0.85; }
.nav .sub { padding-left: 14px; border-left: 1px solid var(--border-color); margin-left: 16px; }
.userbox { padding: 14px; border-top: 1px solid var(--border-color); display: flex; align-items: center; gap: 10px; }
.avatar { width: 34px; height: 34px; border-radius: 50%; background: var(--primary-color); color: #fff; display:flex; align-items:center; justify-content:center; font-weight:600; font-size:13px; }
.userbox .meta { line-height: 1.2; }
.userbox .nm { font-weight: 600; font-size: 13px; }
.userbox .rl { font-size: 11px; color: var(--text-tertiary); }
/* ===== Main ===== */
.main { flex: 1; min-width: 0; display: flex; flex-direction: column; overflow: hidden; }
.topbar {
height: 56px; flex-shrink: 0; border-bottom: 1px solid var(--border-color);
display: flex; align-items: center; justify-content: space-between; padding: 0 24px;
background: var(--bg-primary);
}
.crumb { font-size: 13px; color: var(--text-tertiary); }
.crumb b { color: var(--text-primary); font-weight: 600; }
.topbar .right { display: flex; align-items: center; gap: 14px; color: var(--text-tertiary); font-size: 13px; }
.content { flex: 1; overflow-y: auto; padding: 24px 28px; background: var(--bg-primary); }
.wrap { max-width: 1180px; margin: 0 auto; }
/* ===== Page header ===== */
.pagehead { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 22px; }
.pagehead h1 { margin: 0 0 4px; font-size: 23px; font-weight: 700; letter-spacing: -0.01em; }
.pagehead p { margin: 0; color: var(--text-secondary); font-size: 13.5px; max-width: 640px; }
/* ===== Buttons ===== */
.btn { display: inline-flex; align-items: center; gap: 8px; border: none; border-radius: var(--radius-sm); font-family: var(--font); font-weight: 500; font-size: 14px; padding: 8px 18px; cursor: pointer; transition: all .18s cubic-bezier(.4,0,.2,1); letter-spacing: .01em; white-space: nowrap; }
.btn-primary { background: linear-gradient(180deg, var(--primary-color), var(--primary-color-dark)); color: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.12), inset 0 1px 0 rgba(255,255,255,.12); }
.btn-primary:hover { transform: translateY(-1px); box-shadow: 0 2px 6px rgba(0,0,0,.16); }
.btn-secondary { background: #fff; color: var(--text-secondary); border: 1px solid var(--border-color); box-shadow: 0 1px 2px rgba(0,0,0,.06); }
.btn-secondary:hover { background: var(--gray); color: #fff; border-color: var(--gray); }
.btn-success { background: linear-gradient(180deg, var(--success), #2F855A); color: #fff; }
.btn-success:hover { transform: translateY(-1px); }
.btn-ghost { background: transparent; color: var(--primary-color); border: 1px solid transparent; }
.btn-ghost:hover { background: var(--primary-light); }
.btn-sm { padding: 6px 13px; font-size: 12.5px; }
.btn[disabled] { opacity: .5; cursor: not-allowed; }
/* ===== Cards / list ===== */
.toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; }
.search { flex: 1; max-width: 320px; position: relative; }
.search input { width: 100%; padding: 8px 12px 8px 32px; border: 1px solid var(--border-color); border-radius: var(--radius-sm); font-family: var(--font); font-size: 13.5px; background: #fff; }
.search .ic { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: var(--text-tertiary); }
.seg { display: inline-flex; border: 1px solid var(--border-color); border-radius: var(--radius-sm); overflow: hidden; }
.seg button { border: none; background: #fff; padding: 7px 14px; font-family: var(--font); font-size: 13px; color: var(--text-secondary); cursor: pointer; }
.seg button.on { background: var(--primary-light); color: var(--primary-color-dark); font-weight: 600; }
.seg button + button { border-left: 1px solid var(--border-color); }
.sol-list { display: grid; gap: 12px; }
.sol-card {
border: 1px solid var(--border-color); border-radius: var(--radius-md); background: #fff;
padding: 16px 18px; display: grid; grid-template-columns: 42px 1fr auto; gap: 14px; align-items: center;
cursor: pointer; transition: all .15s ease;
}
.sol-card:hover { border-color: var(--border-dark); box-shadow: 0 4px 14px rgba(0,0,0,.06); transform: translateY(-1px); }
.sol-ic { width: 42px; height: 42px; border-radius: var(--radius-md); display: flex; align-items: center; justify-content: center; font-size: 20px; background: var(--primary-light); }
.sol-main .nm { font-weight: 600; font-size: 15px; margin-bottom: 3px; }
.sol-main .ds { color: var(--text-secondary); font-size: 13px; }
.sol-meta { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; text-align: right; }
.sol-meta .line { font-size: 12px; color: var(--text-tertiary); }
.sol-meta .line b { color: var(--text-secondary); font-weight: 600; }
.badge { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 600; padding: 3px 9px; border-radius: 999px; }
.badge .d { width: 7px; height: 7px; border-radius: 50%; }
.b-active { background: var(--success-bg); color: #22643f; }
.b-active .d { background: var(--success); }
.b-inactive { background: #EDF2F7; color: var(--text-secondary); }
.b-inactive .d { background: var(--gray); }
.b-error { background: var(--error-bg); color: #822; }
.b-error .d { background: var(--error); }
.b-running { background: var(--primary-light); color: var(--primary-color-dark); }
.b-running .d { background: var(--primary-color); animation: pulse 1.2s infinite; }
.b-warn { background: #FEFCBF; color: #744210; }
.b-warn .d { background: var(--warning); }
@keyframes pulse { 0%,100%{opacity:1;} 50%{opacity:.3;} }
/* ===== Detail ===== */
.backlink { display: inline-flex; align-items: center; gap: 6px; color: var(--text-secondary); font-size: 13px; cursor: pointer; margin-bottom: 14px; background:none; border:none; font-family:var(--font); padding:0;}
.backlink:hover { color: var(--primary-color); }
.detail-head { display: flex; align-items: flex-start; gap: 16px; margin-bottom: 18px; }
.detail-head .sol-ic { width: 52px; height: 52px; font-size: 25px; }
.detail-head h1 { margin: 0 0 5px; font-size: 21px; }
.detail-head .sub { color: var(--text-secondary); font-size: 13px; }
.detail-actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }
.tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--border-color); margin-bottom: 22px; }
.tabs button { border: none; background: none; font-family: var(--font); font-size: 14px; font-weight: 500; color: var(--text-secondary); padding: 11px 16px; cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; }
.tabs button:hover { color: var(--text-primary); }
.tabs button.on { color: var(--primary-color-dark); border-bottom-color: var(--primary-color); font-weight: 600; }
.tabpane { display: none; }
.tabpane.on { display: block; animation: fade .2s ease; }
@keyframes fade { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.grid2 { display: grid; grid-template-columns: 1fr 320px; gap: 22px; align-items: start; }
@media (max-width: 900px){ .grid2 { grid-template-columns: 1fr; } }
.card { border: 1px solid var(--border-color); border-radius: var(--radius-md); background: #fff; overflow: hidden; }
.card-h { padding: 13px 16px; border-bottom: 1px solid var(--border-color); font-weight: 600; font-size: 14px; background: var(--bg-secondary); display:flex; align-items:center; justify-content:space-between; }
.card-h .hint { font-weight: 500; font-size: 11.5px; color: var(--text-tertiary); }
.card-b { padding: 16px; }
.field { margin-bottom: 16px; }
.field:last-child { margin-bottom: 0; }
.field label { display: block; font-weight: 600; font-size: 12.5px; margin-bottom: 6px; }
.field .desc { font-size: 11.5px; color: var(--text-tertiary); margin: -3px 0 7px; }
.field input[type=text], .field input[type=number], .field select, .field textarea {
width: 100%; padding: 8px 11px; border: 1px solid var(--border-color); border-radius: var(--radius-sm);
font-family: var(--font); font-size: 13.5px; background: #fff; color: var(--text-primary);
}
.field input:focus, .field select:focus, .field textarea:focus { outline: none; border-color: var(--primary-color); box-shadow: 0 0 0 3px var(--primary-light); }
.row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.chips { display: flex; flex-wrap: wrap; gap: 7px; }
.chip { display: inline-flex; align-items: center; gap: 6px; background: var(--primary-light); color: var(--primary-color-dark); border-radius: 999px; padding: 5px 11px; font-size: 12.5px; font-weight: 500; }
.chip .x { cursor: pointer; opacity: .6; }
.chip.add { background: #fff; border: 1px dashed var(--border-dark); color: var(--text-secondary); cursor: pointer; }
.toggle { display: inline-flex; align-items: center; gap: 9px; cursor: pointer; }
.switch { width: 38px; height: 22px; border-radius: 999px; background: var(--success); position: relative; transition: background .2s; }
.switch::after { content: ""; position: absolute; top: 2px; left: 18px; width: 18px; height: 18px; border-radius: 50%; background: #fff; transition: left .2s; box-shadow: 0 1px 2px rgba(0,0,0,.2); }
.switch.off { background: var(--border-dark); }
.switch.off::after { left: 2px; }
.sidecard .kv { display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px dashed var(--border-color); font-size: 13px; }
.sidecard .kv:last-child { border-bottom: none; }
.sidecard .kv span { color: var(--text-tertiary); }
.sidecard .kv b { font-weight: 600; }
table.runs { width: 100%; border-collapse: collapse; font-size: 13px; }
table.runs th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-tertiary); padding: 9px 14px; border-bottom: 1px solid var(--border-color); background: var(--bg-secondary); }
table.runs td { padding: 11px 14px; border-bottom: 1px solid var(--border-color); }
table.runs tr:hover td { background: var(--bg-secondary); }
table.runs tr:last-child td { border-bottom: none; }
.mono { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 12px; color: var(--text-secondary); }
/* run trace steps */
.trace { display: grid; gap: 8px; }
.step { display: grid; grid-template-columns: 24px 1fr auto; gap: 11px; align-items: center; padding: 10px 13px; border: 1px solid var(--border-color); border-radius: var(--radius-sm); background: #fff; }
.step .dotc { width: 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 12px; color: #fff; }
.step .nm { font-weight: 500; }
.step .nm small { color: var(--text-tertiary); font-weight: 400; }
.step .dur { font-size: 12px; color: var(--text-tertiary); }
.ok { background: var(--success); }
.warnc { background: var(--warning); }
/* output files */
.files { display: grid; gap: 10px; }
.file { display: grid; grid-template-columns: 38px 1fr auto; gap: 12px; align-items: center; padding: 11px 14px; border: 1px solid var(--border-color); border-radius: var(--radius-sm); background: #fff; }
.file .pic { width: 38px; height: 38px; border-radius: var(--radius-sm); background: var(--error-bg); color: #9b2c2c; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 11px; }
.file .nm { font-weight: 500; }
.file .mt { font-size: 12px; color: var(--text-tertiary); }
.graph-strip { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 14px; background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: var(--radius-md); margin-top: 14px; }
.gnode { background: #fff; border: 1px solid var(--border-dark); border-radius: var(--radius-sm); padding: 7px 11px; font-size: 12px; font-weight: 500; display: flex; align-items: center; gap: 6px; }
.gnode .tag { font-size: 10px; background: var(--primary-light); color: var(--primary-color-dark); padding: 1px 6px; border-radius: 4px; font-weight: 600; }
.garrow { color: var(--text-tertiary); }
.gnode.ai { border-color: var(--primary-color); }
.note { display: flex; gap: 9px; padding: 11px 13px; border-radius: var(--radius-sm); font-size: 12.5px; line-height: 1.5; }
.note-info { background: var(--primary-light); color: var(--primary-color-dark); }
.note-warn { background: #FEFCBF; color: #744210; }
/* ===== Modal ===== */
.overlay { position: fixed; inset: 0; background: rgba(26,32,44,.5); display: none; align-items: center; justify-content: center; z-index: 100; padding: 24px; }
.overlay.on { display: flex; }
.modal { background: #fff; border-radius: var(--radius-lg); width: 100%; max-width: 720px; max-height: 88vh; overflow: hidden; display: flex; flex-direction: column; box-shadow: 0 24px 60px rgba(0,0,0,.3); }
.modal-h { padding: 18px 22px; border-bottom: 1px solid var(--border-color); display: flex; align-items: center; justify-content: space-between; }
.modal-h h2 { margin: 0; font-size: 18px; }
.modal-h .close { background: none; border: none; font-size: 22px; color: var(--text-tertiary); cursor: pointer; line-height: 1; }
.modal-b { padding: 22px; overflow-y: auto; }
.modal-f { padding: 16px 22px; border-top: 1px solid var(--border-color); display: flex; justify-content: flex-end; gap: 10px; }
.tmpl-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 640px){ .tmpl-grid { grid-template-columns: 1fr; } }
.tmpl { border: 1px solid var(--border-color); border-radius: var(--radius-md); padding: 14px; cursor: pointer; transition: all .15s; }
.tmpl:hover, .tmpl.sel { border-color: var(--primary-color); background: var(--primary-light); }
.tmpl .ti { font-size: 22px; margin-bottom: 8px; }
.tmpl .tn { font-weight: 600; font-size: 14px; margin-bottom: 3px; }
.tmpl .td { font-size: 12px; color: var(--text-secondary); }
.divider { display: flex; align-items: center; gap: 12px; margin: 20px 0; color: var(--text-tertiary); font-size: 12px; }
.divider::before, .divider::after { content: ""; flex: 1; height: 1px; background: var(--border-color); }
.toast { position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%) translateY(20px); background: var(--text-primary); color: #fff; padding: 12px 20px; border-radius: var(--radius-md); font-size: 13.5px; font-weight: 500; box-shadow: 0 8px 24px rgba(0,0,0,.25); opacity: 0; transition: all .25s; z-index: 200; display: flex; align-items: center; gap: 9px; }
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.toast .d { width: 8px; height: 8px; border-radius: 50%; background: var(--success); }
</style>
</head>
<body>
<div class="app">
<!-- Sidebar -->
<aside class="sidebar">
<div class="logo"><span class="dot">P</span><span><span class="pow">Power</span><span class="on">On</span></span></div>
<nav class="nav">
<div class="group">Plattform</div>
<a><span class="ic"></span> Dashboard</a>
<a><span class="ic"></span> Workspace</a>
<div class="group">Feature · Trustee</div>
<a><span class="ic"></span> Übersicht</a>
<a><span class="ic">🧾</span> Belege</a>
<a><span class="ic">📊</span> Buchhaltungssystem</a>
<a><span class="ic">🔌</span> Datenquellen</a>
<a class="active"><span class="ic"></span> Lösungen</a>
<div class="group">Administration</div>
<a><span class="ic">👥</span> Benutzer &amp; Rollen</a>
<a><span class="ic">💳</span> Abrechnung</a>
</nav>
<div class="userbox">
<div class="avatar">PB</div>
<div class="meta"><div class="nm">Päde Bruderer</div><div class="rl">trustee-admin · Pling</div></div>
</div>
</aside>
<!-- Main -->
<div class="main">
<div class="topbar">
<div class="crumb">Trustee · <b id="crumb">Lösungen</b></div>
<div class="right"><span>Kaffee-Klatsch Holding</span><span>·</span><span>◑ Hell</span></div>
</div>
<div class="content">
<div class="wrap">
<!-- ===================== VIEW: LIST ===================== -->
<section id="viewList">
<div class="pagehead">
<div>
<h1>Lösungen</h1>
<p>Wiederkehrende Aufgaben als konfigurierte Workflows — einmal einstellen, automatisch laufen lassen, Ergebnisse ansehen. Kein Code nötig.</p>
</div>
<button class="btn btn-primary" onclick="openCatalog()"><span></span> Neue Lösung</button>
</div>
<div class="toolbar">
<div class="search"><span class="ic"></span><input type="text" placeholder="Lösungen durchsuchen…" /></div>
<div class="seg">
<button class="on">Alle</button>
<button>Aktiv</button>
<button>Inaktiv</button>
</div>
</div>
<div class="sol-list" id="solList"></div>
</section>
<!-- ===================== VIEW: DETAIL ===================== -->
<section id="viewDetail" style="display:none;">
<button class="backlink" onclick="showList()">← Zurück zu Lösungen</button>
<div class="detail-head">
<div class="sol-ic" id="dIcon">📊</div>
<div>
<h1 id="dName"></h1>
<div class="sub" id="dSub"></div>
</div>
<div class="detail-actions">
<button class="btn btn-secondary btn-sm" onclick="toast('Workflow im Graphical Editor geöffnet')">Im Editor öffnen</button>
<button class="btn btn-success btn-sm" id="dRunBtn" onclick="runNow()">▶ Jetzt ausführen</button>
</div>
</div>
<div class="tabs">
<button class="on" onclick="switchTab(event,'tEinst')">Einstellungen</button>
<button onclick="switchTab(event,'tTest')">Testlauf</button>
<button onclick="switchTab(event,'tRuns')">Läufe</button>
<button onclick="switchTab(event,'tOut')">Ausgabe</button>
</div>
<!-- TAB: Einstellungen -->
<div class="tabpane on" id="tEinst">
<div class="grid2">
<div style="display:grid; gap:18px;">
<div class="card">
<div class="card-h">Konfiguration <span class="hint">aus settingsSchema generiert</span></div>
<div class="card-b" id="settingsBody"></div>
</div>
<div class="card">
<div class="card-h">Trigger &amp; Zeitplan</div>
<div class="card-b" id="triggerBody"></div>
</div>
</div>
<div style="display:grid; gap:18px;">
<div class="card sidecard">
<div class="card-h">Status</div>
<div class="card-b" id="statusBody"></div>
</div>
<div class="card">
<div class="card-h">Workflow</div>
<div class="card-b">
<div style="font-size:12.5px; color:var(--text-secondary); margin-bottom:8px;">Diese Lösung kapselt einen Graphen aus vorhandenen Bausteinen:</div>
<div id="graphStrip"></div>
</div>
</div>
</div>
</div>
<div style="display:flex; justify-content:flex-end; gap:10px; margin-top:18px;">
<button class="btn btn-secondary" onclick="showList()">Abbrechen</button>
<button class="btn btn-primary" onclick="toast('Einstellungen gespeichert')">Speichern</button>
</div>
</div>
<!-- TAB: Testlauf -->
<div class="tabpane" id="tTest">
<div class="card">
<div class="card-h">Probelauf (Dry-Run) <span class="hint">keine Mails, keine Seiteneffekte</span></div>
<div class="card-b">
<p style="margin-top:0; color:var(--text-secondary); font-size:13.5px;">Führt die Lösung mit den aktuellen Einstellungen testweise aus. Reports werden erzeugt und angezeigt, aber <b>nicht</b> versendet.</p>
<button class="btn btn-primary" onclick="startTest()">▶ Testlauf starten</button>
<div id="testTrace" style="margin-top:18px;"></div>
</div>
</div>
</div>
<!-- TAB: Läufe -->
<div class="tabpane" id="tRuns">
<div class="card">
<div class="card-h">Lauf-Historie</div>
<table class="runs" id="runsTable"></table>
</div>
<div class="card" style="margin-top:18px;">
<div class="card-h">Lauf-Trace <span class="hint">Lauf #1042 · 15.05.2026 06:00</span></div>
<div class="card-b">
<div class="trace" id="traceBody"></div>
</div>
</div>
</div>
<!-- TAB: Ausgabe -->
<div class="tabpane" id="tOut">
<div class="card">
<div class="card-h">Erzeugte Dokumente <span class="hint">archiviert im Mandanten-Datenraum</span></div>
<div class="card-b"><div class="files" id="filesBody"></div></div>
</div>
</div>
</section>
</div>
</div>
</div>
</div>
<!-- ===================== MODAL: Katalog / Neu ===================== -->
<div class="overlay" id="catalog">
<div class="modal">
<div class="modal-h">
<h2>Neue Lösung anlegen</h2>
<button class="close" onclick="closeCatalog()">×</button>
</div>
<div class="modal-b">
<div style="font-weight:600; margin-bottom:12px; font-size:14px;">Aus Vorlage (Use-Case-Katalog)</div>
<div class="tmpl-grid">
<div class="tmpl" onclick="selTmpl(this)"><div class="ti">🔄</div><div class="tn">Systeme synchronisieren</div><div class="td">Quelle → Ziel, periodisch (z. B. SelectLine → RMA)</div></div>
<div class="tmpl" onclick="selTmpl(this)"><div class="ti">📈</div><div class="tn">Periodisches Reporting</div><div class="td">Daten konsolidieren, PDF erzeugen, verteilen</div></div>
<div class="tmpl" onclick="selTmpl(this)"><div class="ti">📥</div><div class="tn">Dokumente verarbeiten</div><div class="td">Dateien einlesen, KI-Auswertung, Antwort</div></div>
<div class="tmpl" onclick="selTmpl(this)"><div class="ti">✉️</div><div class="tn">Benachrichtigung</div><div class="td">Bei Ereignis rollenbasiert mailen</div></div>
</div>
<div class="divider">oder mit KI beschreiben</div>
<div class="field">
<label>Beschreibe dein Bedürfnis — die KI baut den Workflow</label>
<div class="desc">Der Workflow-Agent komponiert daraus einen Graphen aus vorhandenen Bausteinen. Du konfigurierst danach nur noch die Einstellungen.</div>
<textarea rows="3" placeholder="z. B. «Schicke mir am 15. jedes Monats einen konsolidierten Bericht über alle 5 Store-Buchhaltungen und je einen Kennzahlen-Report an jeden Store-Manager.»"></textarea>
</div>
<div class="note note-info"><span></span><span>Vorlagen werden deterministisch instanziiert (kein KI-Risiko). KI-Generierung erzeugt einen Entwurf, den du vor dem Aktivieren prüfst.</span></div>
</div>
<div class="modal-f">
<button class="btn btn-secondary" onclick="closeCatalog()">Abbrechen</button>
<button class="btn btn-primary" onclick="generateSolution()">✦ Lösung erstellen</button>
</div>
</div>
</div>
<div class="toast" id="toast"><span class="d"></span><span id="toastMsg">Gespeichert</span></div>
<script>
const solutions = {
pling: {
icon: "📊",
name: "Monatsreporting Kaffee-Klatsch",
sub: "Periodisches Reporting · 5 RMA-Buchhaltungen · aus Vorlage",
status: "active",
statusLabel: "Aktiv",
lastRun: "15.05.2026 06:00 · erfolgreich",
nextRun: "15.06.2026 06:00",
restricted: true,
kv: [
["Status", '<span class="badge b-active"><span class="d"></span>Aktiv</span>'],
["Letzter Lauf", "15.05.2026 · OK"],
["Nächster Lauf", "15.06.2026 06:00"],
["Läufe gesamt", "7"],
["Erfolgsquote", "100%"],
["Instanzen", "5 Stores"]
],
settings: `
<div class="field">
<label>Feature-Instanzen (Fan-out)</label>
<div class="desc">Über welche Buchhaltungen läuft die Lösung — eine Solution, mehrere Instanzen.</div>
<div class="chips">
<span class="chip">Coffeeshop Zürich <span class="x">×</span></span>
<span class="chip">Coffeeshop Bern <span class="x">×</span></span>
<span class="chip">Coffeeshop Basel <span class="x">×</span></span>
<span class="chip">Coffeeshop Luzern <span class="x">×</span></span>
<span class="chip">Coffeeshop St. Gallen <span class="x">×</span></span>
<span class="chip add"> Instanz</span>
</div>
</div>
<div class="field">
<label>Berichts-Periode</label>
<div class="row2">
<select><option>Vormonat (Standard)</option><option>Year-to-date</option><option>Freie Periode</option></select>
<input type="text" value="Mai 2026" />
</div>
</div>
<div class="field">
<label>Konten-Bereiche</label>
<div class="desc">Kundenspezifisch — als Settings, nicht im Code.</div>
<div class="row2">
<div><div style="font-size:11px;color:var(--text-tertiary);margin-bottom:4px;">Umsatz</div><input type="text" value="30003999"/></div>
<div><div style="font-size:11px;color:var(--text-tertiary);margin-bottom:4px;">Warenkosten</div><input type="text" value="60006299"/></div>
</div>
<div class="row2" style="margin-top:10px;">
<div><div style="font-size:11px;color:var(--text-tertiary);margin-bottom:4px;">Personalaufwand</div><input type="text" value="50005099"/></div>
<div></div>
</div>
</div>
<div class="field">
<label>Empfänger (rollenbasiert)</label>
<div class="desc">Verteiler wird automatisch aus Trustee-Rollen aufgelöst — keine Listen pflegen (rbac.queryUsersByRole).</div>
<div class="chips">
<span class="chip">Holding-Bericht → trustee-accountant <span class="x">×</span></span>
<span class="chip">Store-Kennzahlen → trustee-client <span class="x">×</span></span>
<span class="chip">Lauf-Protokoll → trustee-admin <span class="x">×</span></span>
</div>
</div>
<div class="field">
<label class="toggle"><span class="switch off"></span> Bei unvollständiger Buchhaltung blockieren</label>
<div class="desc">Aus = durchlaufen &amp; im Bericht markieren (stopOnIncomplete: false). Ein = warten bis alle 5 fertig.</div>
</div>`,
trigger: `
<div class="field">
<label class="toggle"><span class="switch"></span> Geplant (Zeitplan)</label>
<div class="desc" style="margin-left:48px;">Cron: <span class="mono">0 6 15 * *</span> · Europe/Zurich — am 15. um 06:00.</div>
</div>
<div class="row2">
<div class="field"><label>Tag im Monat</label><input type="number" value="15"/></div>
<div class="field"><label>Uhrzeit</label><input type="text" value="06:00"/></div>
</div>
<div class="field">
<label class="toggle"><span class="switch"></span> Manueller Start erlaubt</label>
</div>
<div class="field">
<label>Wer darf manuell starten</label>
<div class="desc">Zugriffskontrolle am Trigger (accessControl.requiredRoles).</div>
<select><option>Nur trustee-admin</option><option>trustee-admin + trustee-accountant</option><option>Alle mit Zugriff</option></select>
</div>`,
graph: [
["trigger", "Zeitplan / Manuell"],
["loop", "5 Instanzen"],
["trustee", "Salden holen"],
["data", "Konsolidieren"],
["ai", "6 PDFs erzeugen", true],
["rbac", "Empfänger auflösen"],
["outlook", "Versenden"]
],
runs: [
["#1042", "15.05.2026 06:00", "Zeitplan", "active", "Erfolgreich", "2m 14s", "6 PDFs · 8 Mails"],
["#1041", "15.04.2026 06:00", "Zeitplan", "warn", "Mit Hinweis", "2m 41s", "1 BuHa unvollständig"],
["#1038", "15.03.2026 06:00", "Zeitplan", "active", "Erfolgreich", "2m 02s", "6 PDFs · 8 Mails"],
["#1031", "21.02.2026 14:22", "Manuell · Päde", "active", "Erfolgreich", "2m 10s", "Ad-hoc YTD"]
],
trace: [
["ok", "trigger.scheduled", "Cron 0 6 15 * *", "0.1s"],
["ok", "flow.loop · 5 Instanzen", "parallel, concurrency 5", "1.2s"],
["ok", "trustee.refreshAccountingData", "5/5 Buchhaltungen gesynct", "44s"],
["ok", "trustee.queryData · Salden", "akt. + Vorjahr", "9s"],
["ok", "data.consolidate", "sumByKey → HoldingFigures", "0.6s"],
["ok", "ai.generateDocument · Holding", "1 PDF, neutralisiert", "31s"],
["ok", "ai.generateDocument · Store-KPI ×5", "5 PDFs", "26s"],
["ok", "rbac.queryUsersByRole", "8 Empfänger aufgelöst", "0.4s"],
["ok", "outlook.send", "8 Mails versendet", "3s"]
],
files: [
["Monatsbericht Holding Mai 2026", "PDF · 412 KB · Holding-Instanz", "PDF"],
["Kennzahlen Coffeeshop Zürich", "PDF · 88 KB · Store-Instanz", "PDF"],
["Kennzahlen Coffeeshop Bern", "PDF · 86 KB · Store-Instanz", "PDF"],
["Kennzahlen Coffeeshop Basel", "PDF · 87 KB · Store-Instanz", "PDF"],
["Kennzahlen Coffeeshop Luzern", "PDF · 85 KB · Store-Instanz", "PDF"],
["Kennzahlen Coffeeshop St. Gallen", "PDF · 84 KB · Store-Instanz", "PDF"]
]
},
selectline: {
icon: "🔄",
name: "SelectLine → RMA Sync",
sub: "Systeme synchronisieren · täglich · aus Vorlage",
status: "active", statusLabel: "Aktiv",
lastRun: "04.06.2026 06:00 · erfolgreich", nextRun: "05.06.2026 06:00",
restricted: false,
kv: [
["Status", '<span class="badge b-active"><span class="d"></span>Aktiv</span>'],
["Letzter Lauf", "04.06.2026 · OK"],
["Nächster Lauf", "05.06.2026 06:00"],
["Läufe gesamt", "63"],
["Erfolgsquote", "98%"]
],
settings: `
<div class="field"><label>Quell-System</label><select><option>SelectLine (API)</option></select></div>
<div class="field"><label>Ziel-System</label><select><option>RunMyAccounts (RMA)</option></select></div>
<div class="field">
<label>Konten-Mapping</label>
<div class="desc">Zuordnung Quell- zu Zielkonten — kundenspezifisch, als Settings.</div>
<div class="chips"><span class="chip">1000 → 1020 <span class="x">×</span></span><span class="chip">3400 → 3000 <span class="x">×</span></span><span class="chip add"> Mapping</span></div>
</div>
<div class="field"><label class="toggle"><span class="switch"></span> Duplikat-Prüfung aktiv</label></div>`,
trigger: `
<div class="field"><label class="toggle"><span class="switch"></span> Geplant (täglich)</label><div class="desc" style="margin-left:48px;">Cron <span class="mono">0 6 * * *</span> · Europe/Zurich</div></div>
<div class="field"><label>Uhrzeit</label><input type="text" value="06:00"/></div>`,
graph: [["trigger","Täglich 06:00"],["selectline","Rechnungen lesen"],["data","Mapping"],["rma","Buchen", true]],
runs: [
["#0631","04.06.2026 06:00","Zeitplan","active","Erfolgreich","48s","14 Rechnungen"],
["#0630","03.06.2026 06:00","Zeitplan","active","Erfolgreich","51s","9 Rechnungen"],
["#0629","02.06.2026 06:00","Zeitplan","error","Fehler","12s","API-Timeout SelectLine"]
],
trace: [
["ok","trigger.scheduled","Cron 0 6 * * *","0.1s"],
["ok","selectline.listInvoices","14 neue Rechnungen","6s"],
["ok","data.mapAccounts","Mapping angewandt","0.3s"],
["ok","rma.pushInvoice","14 gebucht, 0 Duplikate","41s"]
],
files: [["Sync-Protokoll 04.06.2026","CSV · 12 KB","CSV"]]
},
pwg: {
icon: "📥",
name: "Mietzins-Bestätigungen (PWG)",
sub: "Dokumente verarbeiten · Pilot · per KI generiert",
status: "inactive", statusLabel: "Inaktiv (Entwurf)",
lastRun: "—", nextRun: "nicht aktiviert",
restricted: false,
kv: [
["Status", '<span class="badge b-inactive"><span class="d"></span>Inaktiv</span>'],
["Herkunft", "KI-Entwurf"],
["Letzter Lauf", "—"],
["Nächster Lauf", "nicht aktiviert"]
],
settings: `
<div class="field"><label>SharePoint-Ordner</label><input type="text" value="/Mietzins/Eingang 2026"/></div>
<div class="field"><label>Abacus-Mandant</label><select><option>PWG Immobilien AG</option></select></div>
<div class="field"><label>Empfänger (Übersicht)</label><div class="chips"><span class="chip">trustee-accountant <span class="x">×</span></span><span class="chip add"> Rolle</span></div></div>
<div class="note note-warn"><span></span><span>KI-Entwurf — bitte Einstellungen prüfen und einen Testlauf machen, bevor du aktivierst.</span></div>`,
trigger: `<div class="field"><label class="toggle"><span class="switch off"></span> Geplant</label><div class="desc" style="margin-left:48px;">Noch nicht aktiviert.</div></div>`,
graph: [["trigger","Manuell"],["sharepoint","Dateien lesen"],["loop","pro Datei"],["ai","Extrahieren", true],["data","Schreiben"],["email","Antwort"]],
runs: [],
trace: [],
files: []
}
};
const listOrder = ["pling","selectline","pwg"];
function _badge(s){
const map = { active:["b-active","Aktiv"], inactive:["b-inactive","Inaktiv"], error:["b-error","Fehler"], warn:["b-warn","Hinweis"], running:["b-running","Läuft"] };
const [cls,lbl] = map[s] || map.inactive;
return `<span class="badge ${cls}"><span class="d"></span>${lbl}</span>`;
}
function renderList(){
const el = document.getElementById("solList");
el.innerHTML = listOrder.map(id => {
const s = solutions[id];
return `<div class="sol-card" onclick="showDetail('${id}')">
<div class="sol-ic">${s.icon}</div>
<div class="sol-main">
<div class="nm">${s.name}</div>
<div class="ds">${s.sub}</div>
</div>
<div class="sol-meta">
${_badge(s.status)}
<div class="line">Letzter Lauf: <b>${s.lastRun}</b></div>
<div class="line">Nächster: <b>${s.nextRun}</b></div>
</div>
</div>`;
}).join("");
}
let current = null;
function showDetail(id){
current = id;
const s = solutions[id];
document.getElementById("crumb").textContent = s.name;
document.getElementById("dIcon").textContent = s.icon;
document.getElementById("dName").textContent = s.name;
document.getElementById("dSub").textContent = s.sub;
document.getElementById("settingsBody").innerHTML = s.settings;
document.getElementById("triggerBody").innerHTML = s.trigger;
document.getElementById("statusBody").innerHTML = s.kv.map(([k,v]) => `<div class="kv"><span>${k}</span><b>${v}</b></div>`).join("");
document.getElementById("graphStrip").innerHTML = `<div class="graph-strip">` + s.graph.map((g,i) => {
const arrow = i < s.graph.length-1 ? '<span class="garrow"></span>' : '';
return `<div class="gnode ${g[2]?'ai':''}"><span class="tag">${g[0]}</span>${g[1]}</div>${arrow}`;
}).join("") + `</div>`;
// run button restriction
const rb = document.getElementById("dRunBtn");
if (s.restricted){ rb.title = "Nur trustee-admin"; }
// runs table
const rt = document.getElementById("runsTable");
if (s.runs.length){
rt.innerHTML = `<thead><tr><th>Lauf</th><th>Zeitpunkt</th><th>Auslöser</th><th>Status</th><th>Dauer</th><th>Ergebnis</th></tr></thead><tbody>` +
s.runs.map(r => `<tr><td class="mono">${r[0]}</td><td>${r[1]}</td><td>${r[2]}</td><td>${_badge(r[3])}</td><td>${r[5]}</td><td>${r[6]}</td></tr>`).join("") +
`</tbody>`;
} else {
rt.innerHTML = `<tbody><tr><td style="padding:24px; text-align:center; color:var(--text-tertiary);">Noch keine Läufe — Lösung ist nicht aktiviert.</td></tr></tbody>`;
}
// trace
document.getElementById("traceBody").innerHTML = s.trace.length
? s.trace.map(t => `<div class="step"><span class="dotc ${t[0]==='ok'?'ok':'warnc'}">${t[0]==='ok'?'✓':'!'}</span><span class="nm">${t[1]} <small>· ${t[2]}</small></span><span class="dur">${t[3]}</span></div>`).join("")
: `<div style="color:var(--text-tertiary); font-size:13px;">Kein Lauf vorhanden.</div>`;
// files
document.getElementById("filesBody").innerHTML = s.files.length
? s.files.map(f => `<div class="file"><span class="pic">${f[2]}</span><div><div class="nm">${f[0]}</div><div class="mt">${f[1]}</div></div><button class="btn btn-ghost btn-sm" onclick="toast('Download (Mockup)')">Öffnen</button></div>`).join("")
: `<div style="color:var(--text-tertiary); font-size:13px;">Noch keine Dokumente erzeugt.</div>`;
document.getElementById("viewList").style.display = "none";
document.getElementById("viewDetail").style.display = "block";
// reset to first tab
document.querySelectorAll("#viewDetail .tabs button").forEach((b,i)=>b.classList.toggle("on",i===0));
document.querySelectorAll("#viewDetail .tabpane").forEach((p,i)=>p.classList.toggle("on",p.id==="tEinst"));
document.getElementById("testTrace").innerHTML = "";
document.querySelector(".content").scrollTop = 0;
}
function showList(){
current = null;
document.getElementById("crumb").textContent = "Lösungen";
document.getElementById("viewDetail").style.display = "none";
document.getElementById("viewList").style.display = "block";
}
function switchTab(e, id){
document.querySelectorAll("#viewDetail .tabs button").forEach(b=>b.classList.remove("on"));
e.currentTarget.classList.add("on");
document.querySelectorAll("#viewDetail .tabpane").forEach(p=>p.classList.toggle("on",p.id===id));
}
function startTest(){
const s = solutions[current];
const box = document.getElementById("testTrace");
box.innerHTML = `<div class="note note-info"><span></span><span>Testlauf gestartet — Dry-Run, keine Mails werden versendet.</span></div><div class="trace" id="liveTrace" style="margin-top:12px;"></div>`;
const lt = document.getElementById("liveTrace");
const steps = s.trace.length ? s.trace : [["ok","workflow.run","Beispiel-Schritt","1s"]];
let i = 0;
(function next(){
if (i >= steps.length){ toast("Testlauf erfolgreich · 6 Dokumente erzeugt (nicht versendet)"); return; }
const t = steps[i];
const div = document.createElement("div");
div.className = "step";
div.innerHTML = `<span class="dotc ${t[0]==='ok'?'ok':'warnc'}">${t[0]==='ok'?'✓':'!'}</span><span class="nm">${t[1]} <small>· ${t[2]}</small></span><span class="dur">${t[3]}</span>`;
div.style.opacity = 0;
lt.appendChild(div);
requestAnimationFrame(()=>{ div.style.transition="opacity .25s"; div.style.opacity=1; });
i++; setTimeout(next, 420);
})();
}
function runNow(){
const s = solutions[current];
if (s.restricted) toast("Lauf gestartet (Rolle trustee-admin bestätigt) ▶");
else toast("Lauf gestartet ▶");
}
// catalog modal
function openCatalog(){ document.getElementById("catalog").classList.add("on"); }
function closeCatalog(){ document.getElementById("catalog").classList.remove("on"); document.querySelectorAll(".tmpl").forEach(t=>t.classList.remove("sel")); }
function selTmpl(el){ document.querySelectorAll(".tmpl").forEach(t=>t.classList.remove("sel")); el.classList.add("sel"); }
function generateSolution(){ closeCatalog(); toast("✦ Workflow erstellt — jetzt Einstellungen konfigurieren"); showDetail("pling"); }
// toast
let toastTimer;
function toast(msg){
const t = document.getElementById("toast");
document.getElementById("toastMsg").textContent = msg;
t.classList.add("show");
clearTimeout(toastTimer);
toastTimer = setTimeout(()=>t.classList.remove("show"), 2600);
}
document.getElementById("catalog").addEventListener("click", e => { if (e.target.id === "catalog") closeCatalog(); });
renderList();
</script>
</body>
</html>

View file

@ -0,0 +1,82 @@
<!-- status: idea -->
<!-- started: 2026-06-04 -->
<!-- component: gateway | ui-nyla | platform -->
# Solution-Schicht — Product Summary
> **In einem Satz:** Wir verpacken den vorhandenen Workflow-Stack in eine **Solution-Schicht**, mit der ein Business-Kunde seine wiederkehrenden Aufgaben selbst **anlegt, einstellt, testet, startet und ansieht** — ohne Code pro Kunde.
>
> Volldokument: `2026-06-CustomerCases-step1-architecture.md` · Mockup: `2026-06-CustomerCases-step2-communication-mockup.html` · Umsetzung: `2026-06-CustomerCases-step3-solutions-plan.md` / `-step3-features-plan.md`
## Die Idee dahinter
**Klassische Software ist von gestern.** Statt pro Problem eine Applikation zu *schreiben*, **konfigurieren** wir komplexe Use Cases aus vorhandenen Bausteinen — genau das, was eine AI heute schon tut, wenn sie assistiert: Absicht beschreiben → System komponiert das Ergebnis.
Die Solution-Schicht **produktisiert** das: Der Kunde beschreibt seinen Use Case, der Workflow-Agent komponiert den Graph, das Ergebnis läuft **dauerhaft, geplant und governt**. Massgeschneidert ohne Massanzug-Kosten, Tage statt Monate, Self-Service statt Vendor-Backlog. **Grenzkosten eines neuen Use Cases → fast null.**
Ehrlich zu Ende gedacht: Es verschwindet nicht *alle* Software — die **Bausteine** und einige **tiefe Features** bleiben Code. Aber die vielen massgeschneiderten Einzellösungen, die man bisher pro Kunde gebaut hat, werden zu **Konfiguration**. Genau das ist «konfigurieren statt coden» — der Hebel, der Kunden aufs nächste Level bringt.
## Das SaaS-Asset: Solution vs. Feature
PORTA hat heute zwei Enden: den technischen **Workflow-Editor** und das **Ops-Dashboard**. Es fehlt die **Mitte** — die kundentaugliche Schicht. Genau das ist das Produkt-Asset:
- **Solution = konfigurierter Workflow (Daten).** Aus Bausteinen komponiert, vom Kunden per Settings eingestellt. Time-to-value: **Tage**. Skaliert **ohne** Engineering pro Kunde.
- **Feature = Code.** Eigene Datenmodelle + tiefe, eigene UI (z. B. `lawyer`). Time-to-value: **Wochen**. Nur wo nötig.
**Leitsatz: Solution-first.** Ein Feature bauen wir nur, wenn die Solution-Schicht es nachweislich nicht trägt. So wird «konfigurieren statt coden» der Default — und das macht aus «wir bauen pro Kunde» ein skalierendes SaaS.
| | Solution (Daten) | Feature (Code) |
|---|---|---|
| Datenmodell | nutzt bestehende | eigenes |
| UI | generische «Lösungen»-Seite | eigene, opinionated |
| Erstellung | Settings + Graph | Engineering |
| Beispiele | Pling-Reporting, SelectLine→RMA, PWG | lawyer, commcoach, trustee |
## Die vier Schichten
| | Schicht | Inhalt | Status |
|---|---|---|---|
| **L4** | Solution Surface | Kundentaugliche UX: «Lösungen»-Seite (Liste · Katalog/AI · Detail mit Tabs) | **NEU** |
| **L3** | Solution Definition | Use Case → konfigurierter Workflow: Settings-Schema + Werte + Trigger + Output | **NEU** |
| **L2** | Composition | Graph: AutoWorkflow/Version/Run, Editor, Templates | vorhanden |
| **L1** | Plattform-Toolbox | Connectors, Actions/Nodes, AI, Neutralisierung, Scheduler, RBAC | vorhanden |
**Unsere Arbeit liegt in L3 + L4.** L1/L2 nutzen wir unverändert.
## Grundlage: die Kunden-Cases
Wir bauen aus realen Cases, nicht aus einer Idee. Sie sind die **Akzeptanzkriterien**: trägt der Entwurf den Fall, ist er richtig.
| Case | Bedürfnis | Settings (= Kundenspezifika, Daten) | Output |
|---|---|---|---|
| **Pling** (Leit-Case) | 5 Buchhaltungen → 6 PDFs, rollenbasiert mailen, monatlich | 5 Instanzen, Konten-Ranges, Cron, Empfänger-Rollen | 6 PDFs + Mails |
| **SelectLine→RMA** | Rechnungen täglich ins RMA buchen | Quelle/Ziel, Mapping | Sync-Log |
| **PWG** | Mietzins-Belege verarbeiten + Antwort | Ordner, Mandant, Empfänger | Tabelle + Mail |
| **Lawyer** | Mandatsvorbereitung + Dashboards | — | = **Feature**, nicht Solution |
Was die Cases erzwingen: **Multi-Instanz-Fan-out** (Pling: 1 Solution über 5 Instanzen) und zwei **generische** Bausteine (`rbac.queryUsersByRole`, Trigger-`accessControl`) — wiederverwendbar, kein Kunden-Code.
## L3 — Datenmodell (kurz)
Solution = **dünne Erweiterung von `AutoWorkflow`** + Settings-Record (keine Parallel-Welt → Scheduler/Runs/Versioning greifen unverändert). Felder:
`workflowRef` · `settingsSchema` (auto aus `trigger.form`/exposed Params) · `settingsValues` (inkl. **Instanz-Set**) · `triggerPolicy` (+ `accessControl.requiredRoles`) · `outputBinding` (`file | table | summary`) · `customerFacing`.
## L4 — UI (kurz)
**Eine** «Lösungen»-Seite pro Feature (Start: Trustee) — kein Seiten-Wildwuchs:
- **Liste** (aktiv/inaktiv, letzter/nächster Lauf)
- **Katalog/Neu** (Vorlage wählen oder per AI beschreiben)
- **Detail** mit Tabs: **Einstellungen · Testlauf · Läufe · Ausgabe**
Settings-Formular wird aus dem `settingsSchema` gerendert (FrontendType). «Im Editor öffnen» bleibt die Escape-Hatch nach L2.
## Bauen — erster Schnitt
1. `AutoWorkflow` um `settingsSchema` + `customerFacing` + Instanz-Set erweitern (+ Settings-Record, Migration).
2. 2 System-Templates: «Systeme synchronisieren» (SelectLine→RMA) + «Periodisches Reporting» (Pling).
3. Generische `SolutionsView` im Trustee: Liste + Settings + Testlauf + Aktivieren + Läufe.
4. Generische Bausteine: `rbac.queryUsersByRole`, Trigger-`accessControl`, run-level `testMode` (Kommunikation im Testlauf unterdrücken).
→ End-to-end belegt an **SelectLine→RMA** und **Pling**.

View file

@ -0,0 +1,191 @@
<!-- status: plan -->
<!-- started: 2026-06-04 -->
<!-- component: gateway | ui-nyla | platform -->
<!-- replaces: 2026-06-STEP2-lawyer-feature.md, 2026-06-STEP2-umsystem-integration-connectors-und-datenquellen-seiten.md (Code-Teile), 2026-06-STEP2-pm-consolidated-customer-requirements.md (Feature/Plattform-Teile) -->
# Plan: Features & Plattform-Bausteine — der Code hinter den Solutions
> **Baut auf:** `2026-06-CustomerCases-step1-architecture.md` (Schichten L1L4, Feature-vs-Solution-Grenze).
> **Schwester-Plan:** `2026-06-CustomerCases-step3-solutions-plan.md` (die konfigurierten Use Cases, die diesen Code konsumieren).
> **Konsolidiert/ersetzt:** Lawyer-Feature-Plan + die Code-/Plattform-Teile aus Umsystem-Integration und konsolidiertem Kundenwünsche-Plan.
## Beschreibung und Kontext
Ein **Feature** ist **Code**: eigenes Datenmodell und/oder tiefe, opinionated UI / Domänenlogik, die ein Graph nicht ausdrücken kann (step1-architecture, Entscheidungsmatrix). Dazu zählen auch die **Plattform-Bausteine**, die die Solutions erst möglich machen — sie sind generischer Code (L1/L2/L3/L4), **ohne Kundennamen**.
Dieser Plan bündelt allen **Code**, der zu bauen ist, in zwei Teilen:
- **Teil A — Plattform-Enabler:** die Solution-Schicht selbst (L3/L4), generische Workflow-Bausteine, Connectors, das «Datenquelle = Seite»-Muster. Voraussetzung für *alle* Solutions.
- **Teil B — Vertikale Code-Features:** Module mit eigenem Datenmodell/UI (`lawyer`), bestehende Features (`commcoach`, `trustee`, `neutralization`) und ihre Erweiterungen.
**Leitsatz (step1-architecture):** Solution-first. Code bauen wir nur, wenn (a) es ein generischer Baustein ist, den viele Solutions teilen, oder (b) der Use Case nachweislich nicht als Solution trägt.
## Fokus und kritische Details
- **Generisch, nie kundenspezifisch.** Connectors = reine API-Adapter (Auth + Lesen/Schreiben + Mapping auf kanonische Modelle), keine Geschäftsregeln, keine Kundennamen. Kundenlogik lebt als Solution (Daten).
- **Eine Workflow-Wahrheit.** Die Solution-Schicht ist eine **dünne Erweiterung von `AutoWorkflow`** + Settings-Record, keine Parallel-Welt → Scheduler/Runs/Versioning unverändert.
- **Source vs. Target** ist die wichtigste neue Connector-Achse (macht aus dem Push-Framework ein bidirektionales Integrations-Framework).
- **RBAC strikt feature-instance-scoped**, nicht mit Mandate-Rollen vermischen (`.cursor/rules/rbac-role-separation.mdc`).
- **Neutralisierung + Private LLM** zwingend für jeden LLM-Pfad mit Personendaten (Trustee, Lawyer/Berufsgeheimnis StGB 321).
- **YAGNI bei Connector-Abstraktion:** beim bestehenden `BaseAccountingConnector` bleiben und nur die **Source-Rolle** ergänzen; das generische «Capability-Mixin»-Framework erst ziehen, wenn die zweite Kategorie (Saläre) real wird.
## Teil A — Plattform-Enabler (macht Solutions möglich)
### A1 — Solution-Schicht (L3/L4)
- **`AutoWorkflow` erweitern** um `settingsSchema`, `outputBinding`, `customerFacing`-Flag, **Instanz-Set** (Multi-Instanz-Fan-out). **DB-Migration: ja (Greenfield, additiv).**
- **Settings-Record-Modell** (`settingsValues` pro Solution/Instanz; Secrets verschlüsselt wie Connector-Configs).
- **`settingsSchema` automatisch ableiten** aus `trigger.form` + als «exposed» markierten Node-Params (kuratierte Overrides später).
- **Solution-Routes** (dünn über bestehende Editor-/Run-Routes): CRUD Settings, Test-Run, Activate/Deactivate.
- **`SolutionsView`** (ui-nyla): generische «Lösungen»-Seite pro Feature — Liste · Katalog/Neu · Detail mit Tabs (Einstellungen · Testlauf · Läufe · Ausgabe). Settings-Formular aus `settingsSchema` (FrontendType-getrieben). Registriert wie andere Views (`FeatureView.tsx` + UI-Areas in `main<Feature>.py`).
- **Use-Case-Katalog** als System-Templates (`interfaces/interfaceBootstrap.py`).
- **AI: Use Case → Workflow** über bestehenden Workflow-Agent (Toolbox `workflow`), Draft + Review vor Aktivierung.
- **Output-Renderer** für `outputBinding.kind` = `file` (Datenraum/`TrusteeDocument`), `table` (FormGenerator/Data-Tables), `summary` (`AutoRun`/`AutoStepLog`). `dashboard` später (AI-Report/Canvas-Pipeline).
### A2 — Generische Workflow-Bausteine (Nodes/Actions)
| Baustein | Zweck | Status |
|---|---|---|
| `rbac.queryUsersByRole` | rollenbasierte Empfänger-Auflösung (Verteiler aus Feature-Rollen statt Listen) | **neu** |
| Trigger-`accessControl.requiredRoles` (in `triggerExecutor`) | nur erlaubte Rolle darf manuell auslösen | **neu** |
| run-level `testMode` | Testlauf real, Kommunikations-/Seiteneffekt-Nodes (Mail/Outlook/Teams/Webhook) unterdrücken Versand (loggen «würde senden …») | **neu** |
| `integration.fetchFromSource` / `integration.mapAccounts` / `integration.pushToTarget` | system-agnostischer Source→Target-Import (Quelle/Ziel = Config) | **neu** |
| `data.consolidate` (sumByKey) | Aggregation mehrerer Instanzen (Pling Holding-Konsolidierung) | prüfen/ggf. neu |
| `data.writeToTable` / Tabellen-Output | Ergebnistabellen (PWG-Übersicht) | prüfen/ggf. neu |
| `trigger.event` / DB-Change-Detection | ereignisgetriggerte Solutions (Notification) | **neu (Roadmap)** |
Alle erscheinen über den Editor-Adapter (`graphicalEditor/nodeDefinitions/`) als Bausteine.
### A3 — Connectors (L1, generische API-Adapter)
- **SelectLine-Connector** (Quelle): `accountingConnectorSelectline.py`, implementiert `BaseAccountingConnector`, Auto-Discovery via `accountingRegistry.py`. Methoden: `testConnection`, `getChartOfAccounts`, `getCustomers`/`getVendors`, Lese-Seite für Belege (`getOutgoingInvoices`, Default `[]` in Base). Config: `baseUrl`, `username`, `password` (secret), optional `mandant`.
- **`TrusteeAccountingConfig.role`** (`source` | `target`) → mehrere Connector-Configs pro Instanz (eine Quelle + ein Ziel); `getActiveConfig`/`_resolveConnectorAndConfig` um `role` filtern. Optional `connectorCategory` (`accounting` | `payroll` | `invoicing`). **DB-Migration: ja.**
- **Kanonisches `Invoice`-Modell** prüfen/ergänzen (falls RMA als AR-Rechnung statt GL-Buchung).
- **Source-Pfad in `accountingBridge.py`** additiv (Push-Pfad unverändert).
- **Roadmap-Connectors** (generisch, je 1 Datei + Config): Xero (1.1.11), FileMaker (PWG 1.9.10), Kassensystem/Gastro (1.6, wartet auf Input), Lohn/Swissdec (4.2), Bank-Statement-Import (4.1.2). Je neuer Connector schaltet neue Solutions frei, ohne Architekturänderung.
### A4 — «Datenquelle = Seite» (generische Connector-UI)
- `TrusteeAccountingSettingsView` → generische **`IntegrationSettingsView`** (`category`-Prop): Verbindungen (Connector + Rolle Quelle/Ziel + Credentials + Test), Datenfluss/Import, Daten-Spiegel.
- Neue UI-Areas in `mainTrustee.py` (z. B. `ui.feature.trustee.payroll`) + Mapping in `FeatureView.tsx`**gleiche** Komponente, andere `category`.
- «Buchhaltungssystem» existiert; «Saläre»/«Fakturierung» als Folge-Kategorien (Platzhalter, nicht erste Umsetzung).
## Teil B — Vertikale Code-Features
### B1 — `lawyer` (Mandatsvorbereitung + Dashboards) — NEU
Echtes Feature (eigene Modelle + opinionated UI), das die Plattform-Bausteine bündelt; **konsumiert** die Solution-Schicht (Matter-Prep/Dashboard-Refresh als interne Solutions/Actions).
- **Datenmodell** (`datamodelLawyer.py`): `LawyerMatter`, `LawyerPreparation`, `LawyerDashboardSnapshot`, `LawyerKpi`, `LawyerSourceMap`. **Migration: ja.**
- **Feature-Modul** `mainLawyer.py` + Template-Rollen `lawyer-admin` / `lawyer-user` / `lawyer-viewer` (feature-instance-scoped).
- **Actions** (`methodLawyer/`): `lawyer.prepareMatter`, `lawyer.refreshDashboard`, `lawyer.queryData`.
- **UI** (`ui-nyla/src/components/Lawyer/`): Dashboard-View (Tabs HR/Business/IT/Finance) + Matter-Preparation-View (opinionated, analog Workspace).
- **Connectors:** DMS (SharePoint vorhanden, iManage neu?), E-Mail (Outlook/Exchange), KYC/AML, Konflikt-Check — als generische L1-Bausteine (Teil A3-Muster).
- **Neutralisierung zwingend** (Berufsgeheimnis); Sprache UI primär Englisch (WW/Investor).
- **Demo-Asset:** synthetic Matter `M-DEMO-001` für WW-Präsentation (statisches Briefing-JSON, Backend-frei).
> Begründung Feature statt Solution: eigene Datenmodelle (`LawyerMatter`…), tiefe opinionated UI (Matter-Preparation), Domänenlogik. Dashboards/Matter-Prep dürfen intern Solutions/Actions nutzen — das Feature ist der opinionated Rahmen.
### B2 — `commcoach` (bestehend)
- Feature komplett (10+ Personas inkl. 4 PWG-Immobilien-Personas, Gamification, Seeding). **Erweiterungen:** kundenspezifische Persona-Sets als Daten (z. B. PWG-Knowledge-Set). Kein Neubau.
### B3 — `trustee` (Core, bestehend) — Erweiterungen
- Engine + Accounting-Bridge + Pipeline (`extractFromFiles`/`processDocuments`/`syncToAccounting`) + Connectors (RMA/Bexio/Abacus) bestehen.
- **Erweiterungen als Bausteine** (nicht als Kundenlogik): Firmen-/Lieferanten-Mapping-UI (1.1.4), Buchungsregeln-Engine (1.1.6), Vorsteuer-Automatik (1.1.7), Bank-Statement-Matching (4.1).
- **Migration:** Analyse-Prompt-Templates (Budget/KPI/Cashflow/Prognose/Jahresabschluss) aus `mainTrustee.py` → kuratierte **Solution-Templates** (→ solutions-plan S5). Trustee bleibt Daten-/Connector-Heimat, die Analysen werden Solutions.
### B4 — Plattform-Features (bestehend, Querschnitt)
- `neutralization` (PII-Masking, Private-LLM, Compliance-Audit) — vorhanden; pro Solution/Feature nur konfigurieren.
- Knowledge/RAG, Billing, Multi-Tenancy, Workspace — vorhanden.
- **UI/UX-Härtung** (aus altem Kundenplan Teil 2, plattformweit, nicht Solution/Feature-spezifisch): Empty-State, DE-Placeholder/i18n, Zwischen-Breakpoint 10251280px, Trust-Strip, Billing-Discovery, Connector-Onboarding-Copy. → separate UX-Charge, hier nur referenziert.
## Feature-vs-Solution — Recap (Entscheidungsmatrix)
| Kriterium | → Solution (Daten) | → Feature (Code) |
|---|---|---|
| Eigenes Datenmodell? | nein | ja (`LawyerMatter`) |
| Tiefe opinionated UI? | nein | ja (Matter-Preparation) |
| Aus Bausteinen komponierbar? | ja | nein (Domänenlogik) |
| Beispiel | SelectLine→RMA, Pling, PWG, Analysen | `lawyer`, `commcoach`, `trustee`-Core |
## Betroffene Module
- **Gateway (platform-core):**
- `features/graphicalEditor/``AutoWorkflow`-Erweiterung + Settings-Record + Solution-Routes (A1). **Migration: ja.**
- `workflows/methods/` + `graphicalEditor/nodeDefinitions/` — generische Nodes (A2).
- `workflows/.../triggerExecutor``accessControl.requiredRoles` + `testMode` (A2).
- `features/trustee/accounting/connectors/accountingConnectorSelectline.py` (neu), `accountingConnectorBase.py` (Source-Methode), `accountingBridge.py` (Source-Pfad), `datamodelFeatureTrustee.py` (`role` [+ `connectorCategory`]) — **Migration: ja** (A3).
- `features/lawyer/` (neu, B1) — `mainLawyer.py`, `datamodelLawyer.py`, `methodLawyer/`, Routes. **Migration: ja.**
- `interfaces/interfaceBootstrap.py` — Use-Case-Katalog/System-Templates (A1).
- `serviceCenter/services/serviceAgent/` (Toolbox `workflow`) — Use-Case→Graph (A1).
- **Frontend (ui-nyla):**
- `SolutionsView` (A1), `IntegrationSettingsView` (A4), `Lawyer/`-Komponenten (B1), `FeatureView.tsx`-Registry + UI-Areas.
- **DB-Migration:** ja (Solution-Schicht, `TrusteeAccountingConfig.role`, Lawyer-Modelle).
- **Andere:** RBAC (neue UI-Areas, bestehende Feature-Rollen), Neutralisierung, Billing (Run-/Sync-Volumen).
## Entscheidungen
| Datum | Entscheidung | Begründung |
|-------|-------------|------------|
| 2026-06-04 | Plattform-Bausteine + Solution-Schicht als **generischer Code**, nie kundenspezifisch | macht alle Solutions möglich, hält «kein Kunden-Code» real |
| 2026-06-04 | Connectors = reine Adapter; `source`/`target`-Rolle als neue Achse | bidirektionales Integrations-Framework, additive Erweiterung |
| 2026-06-04 | `lawyer` bleibt **Feature** (eigene Modelle + opinionated UI), nutzt Solution-Schicht intern | Entscheidungsmatrix; Domänenlogik nicht als Graph abbildbar |
| 2026-06-04 | Trustee-Analyse-Prompt-Templates → **Solution-Templates** migrieren | kundentauglich machen; Trustee bleibt Daten-/Connector-Heimat |
| 2026-06-04 | Connector-Abstraktion erst bei zweiter Kategorie (Saläre) generalisieren | YAGNI |
## Umsetzungs-Checkliste
**Teil A (Enabler, zuerst):**
- [ ] `AutoWorkflow`-Erweiterung (`settingsSchema`/`outputBinding`/`customerFacing`/Instanz-Set) + Settings-Record + Migration
- [ ] Solution-Routes (CRUD/Test/Activate) + `SolutionsView` + Settings-Formular-Renderer
- [ ] Output-Renderer `file`/`table`/`summary`
- [ ] `rbac.queryUsersByRole`, Trigger-`accessControl`, run-level `testMode`
- [ ] Integration-Nodes `fetchFromSource`/`mapAccounts`/`pushToTarget` + Editor-Adapter
- [ ] `data.consolidate` / `data.writeToTable` prüfen/ergänzen
- [ ] SelectLine-Connector + `TrusteeAccountingConfig.role` (+ optional `connectorCategory`) + Migration
- [ ] kanonisches `Invoice`-Modell prüfen; Source-Pfad in `accountingBridge` (additiv)
- [ ] `IntegrationSettingsView` (`category`) generalisieren
- [ ] Use-Case-Katalog/System-Templates + Workflow-Agent-Pfad
**Teil B (Features):**
- [ ] `lawyer`: Datenmodell (5 Modelle) + `mainLawyer.py` + 3 Actions + UI (Dashboard/Matter-Prep) + RBAC + Neutralisierung + Demo-Asset
- [ ] `trustee`: Analyse-Templates → Solution-Templates; optional Mapping-UI/Buchungsregeln/Vorsteuer/Bank-Matching
- [ ] `commcoach`: kundenspezifische Persona-/Knowledge-Sets als Daten
- [ ] Roadmap-Connectors nach Bedarf (Xero, FileMaker, Lohn, Kassensystem, Bank-Import)
## Akzeptanzkriterien
| # | Kriterium (Given-When-Then) | Prio |
|---|---|---|
| 1 | Given ein neues Umsystem, When ein Connector-File + Config ergänzt wird, Then ohne Änderung an Registry/Bridge/Editor verfügbar | must |
| 2 | Given `testMode`, When eine Solution testweise läuft, Then erzeugt sie Artefakte, sendet aber keine Kommunikation | must |
| 3 | Given `rbac.queryUsersByRole`, When mit Rollen-Set aufgerufen, Then dedupliziert die korrekten Empfänger (Pling-Verteiler) | must |
| 4 | Given Anwalt mit `lawyer-user`, When Matter-Preparation getriggert, Then strukturiertes Briefing in <90s, PII vor LLM neutralisiert | must |
| 5 | Given Mandate-Rolle ohne `lawyer-*`, When Lawyer-Feature geöffnet, Then Access Denied | must |
| 6 | Given Solution-Schicht, When ein Kunde Settings ändert, Then ohne Code-Deploy wirksam | must |
## Offene Fragen
1. **Solution-Daten-Heimat:** `AutoWorkflow`-Erweiterung (empfohlen) — Settings-Record als eigenes Modell oder JSON-Feld?
2. **`outputBinding`-Schema:** Artefakt-Referenz (Run-Output-Key vs. Document-Query); `table`-Spalten aus Node-Output ableiten?
3. **SelectLine:** on-prem-Erreichbarkeit (VPN/Tunnel/Agent); Zielart RMA (AR vs. GL).
4. **Lawyer-Connectors:** iManage/KYC/Konflikt-Check-APIs — welche mandantenspezifisch, welche generisch?
5. **Connector-Generalisierung:** wann Capability-Mixins (`AccountingCapable`/`PayrollCapable`) ziehen?
## Links
- Architektur: `c-work/0-ideas/2026-06-CustomerCases-step1-architecture.md`
- Solutions: `c-work/0-ideas/2026-06-CustomerCases-step3-solutions-plan.md`
- Bausteine: `b-reference/platform-core/workflow.md`, `b-reference/platform-core/automation.md`, `b-reference/platform-core/features/trustee.md`
- RBAC/Neutralisierung: `b-reference/platform/rbac.md`, `b-reference/platform/neutralization.md`, `.cursor/rules/rbac-role-separation.mdc`
- Lawyer-Kontext (WW): `pamocreate/projects/poweron/customer-walderwyss/`
- Code: `platform-core/modules/features/trustee/accounting/` (Bridge/Base/Registry/Connectors), `features/graphicalEditor/`
## Abschluss
- [ ] Bei Annahme → Build in `c-work/2-build/` (Teil A vor Teil B)
- [ ] `b-reference/` Kanon-Seiten: «Solutions / Customer Workflows», `features/lawyer.md`, Trustee «Source-Connectors»
- [ ] `TOPICS.md` + `_CHANGELOG.md` pro Phase

View file

@ -0,0 +1,199 @@
<!-- status: plan -->
<!-- started: 2026-06-04 -->
<!-- component: gateway | ui-nyla | platform -->
<!-- replaces: 2026-06-STEP2-umsystem-integration-connectors-und-datenquellen-seiten.md, 2026-06-STEP2-pm-consolidated-customer-requirements.md (Solution-Teile) -->
# Plan: Solutions — kundeneigene Workflows als Konfiguration (kein Code)
> **Baut auf:** `2026-06-CustomerCases-step1-architecture.md` (Schichten L1L4, Feature-vs-Solution-Grenze).
> **Schwester-Plan:** `2026-06-CustomerCases-step3-features-plan.md` (der Code dahinter: Solution-Schicht, generische Bausteine, Connectors, vertikale Features).
> **Konsolidiert/ersetzt:** Umsystem-Integration-Plan + die Solution-tauglichen Use Cases aus dem konsolidierten Kundenwünsche-Plan.
## Beschreibung und Kontext
Eine **Solution** ist ein **konfigurierter Workflow** (Daten = Graph + Settings + Trigger + Output-Bindung), der ein wiederkehrendes Kundenbedürfnis erfüllt — **ohne kundenspezifischen Code**. Sie konsumiert die vorhandenen Plattform-Bausteine (L1 Toolbox, L2 Graph) und wird über die neue Solution-Schicht (L3/L4) angelegt, eingestellt, getestet, ausgeführt und angesehen.
Dieser Plan listet die **konkreten Kunden-Use-Cases, die als Solutions** umgesetzt werden. Der Code, den diese Solutions voraussetzen (Solution-Schicht selbst, generische Workflow-Bausteine, Connectors), steht im **features-plan** — eine Solution schreibt nie eigenen Code.
Business-Treiber: jeder Use Case wird zu Konfiguration statt Engineering → Time-to-value in Tagen, Onboarding ohne Entwicklungs-Backlog, Grenzkosten pro Use Case nahe null.
## Fokus und kritische Details
- **Solution = Daten, nie Code.** Konten-Mappings, Empfänger, Perioden, Ordnerpfade, Cron-Zeiten, Instanz-Auswahl = **Settings**. Tauchen Kundennamen oder `if kunde == X` im Code auf, ist die Solution falsch geschnitten.
- **Multi-Instanz-Fan-out.** Eine Solution kann über ein **Set von Feature-Instanzen** laufen (Pling: 5 Stores). Das Settings-Modell trägt eine Instanz-Auswahl.
- **Voraussetzung sind generische Bausteine, keine kundenspezifischen.** Wo ein Baustein fehlt (z. B. `rbac.queryUsersByRole`, ein SelectLine-Connector), wird er **generisch** im features-plan gebaut und hier nur referenziert.
- **Neutralisierung** für jeden LLM-Pfad (Belege/Berichte mit Personendaten) — über das bestehende Gate, selektiv (Namen/Beschreibungen pseudonymisiert, Zahlen/Konten lesbar).
- **Testlauf real, ohne Versand:** Solutions laufen im Test echt, nur Kommunikation wird via run-level `testMode` unterdrückt.
## Ziel und Nicht-Ziele
- **Ziel:** Die häufigsten Kundenbedürfnisse als **kuratierte Solution-Templates** + pro Mandant/Instanz konfigurierte Solutions abbilden.
- **Ziel:** SelectLine→RMA und Pling-Reporting als erste produktive Solutions (Leit-Cases).
- **Ziel:** Nachweis, dass dasselbe Muster Beleg-Import, Dokumentenverarbeitung und Finanz-Analysen trägt.
- **Explizit NICHT:** kundenspezifischer Code pro Solution (→ features-plan baut nur Generisches).
- **Explizit NICHT:** den Graphical Editor ersetzen — Solutions kapseln ihn; «Im Editor öffnen» bleibt Escape-Hatch.
- **Explizit NICHT:** Use Cases, die ein eigenes Datenmodell / tiefe opinionated UI brauchen (→ das sind **Features**, siehe features-plan; z. B. `lawyer`).
## Klassifikation: was wird Solution, was Feature
| Use-Case-Quelle | Umsetzung | Begründung |
|---|---|---|
| SelectLine → RMA (Umsystem) | **Solution** «Systeme synchronisieren» | Komponierbar aus Connectors + Integration-Nodes; Kundenspezifika = Mapping/Settings |
| Pling Kaffee-Klatsch (Monatsreporting) | **Solution** «Periodisches Reporting» | Fan-out + Konsolidierung + AI-Report + rollenbasierte Verteilung, alles Bausteine |
| PWG Jahresmietzinsbestätigungen (1.9c) | **Solution** «Dokumente verarbeiten» | SharePoint→Extract→AI→Tabelle→Mail, 1 AI-Schritt |
| Beleg-/Spesen-Import periodisch (1.1, 1.10.5) | **Solution** «Beleg-Import» | SharePoint/Drive→Trustee-Pipeline, Zeitplan |
| Budget/Soll-Ist, KPI, Cashflow, Prognose, Jahresabschluss-Check, Liquidität (1.21.7, 4.x) | **Solution** «Finanz-Analyse & Reporting» | `queryData`→`ai.generate`→Output (Tabelle/Report); heute Prompt-Templates |
| KPI-/Notification-Verteilung (1.9.12, 4.5.8) | **Solution** «Benachrichtigung/Report» | Trigger→Daten→Report→rollenbasierte Verteilung |
| Lawyer (Mandatsvorbereitung + Dashboards) | **Feature** | Eigene Modelle (`LawyerMatter`…) + opinionated UI |
| CommCoach, Neutralisierung, Trustee-Core | **Feature** (bestehend) | Domänenlogik/eigene UI/Engine |
| Connectors (SelectLine, Xero, FileMaker, Lohn, Kassensystem) | **Feature/Plattform-Baustein** | Generischer Code (L1), kein Kunden-Code → features-plan |
| Solution-Schicht, generische Nodes, `testMode` | **Feature/Plattform-Enabler** | Code, der Solutions erst möglich macht → features-plan |
## Solution-Katalog
Jede Solution = Template (kuratiert) → pro Instanz konfiguriert. Bausteine sind **vorhanden**, sofern nicht als «(neu → features-plan)» markiert.
### S1 — «Systeme synchronisieren» (Pilot: SelectLine → RMA)
| | |
|---|---|
| **Bedürfnis** | Rechnungen aus externem System (SelectLine) periodisch ins RMA buchen |
| **Trigger** | `trigger.schedule` (z. B. täglich 06:00) oder `trigger.manual` |
| **Bausteine (Graph)** | `integration.fetchFromSource` (SelectLine) → `integration.mapAccounts``integration.pushToTarget` (RMA, inkl. Beleg-Upload) *(Nodes + SelectLine-Connector neu → features-plan)* |
| **Settings (L3)** | Quell-Connector + Credentials, Ziel-Connector, Konten-/Steuer-Mapping, Filter (nur Ausgangsrechnungen, «seit letztem Sync»), Zeitplan |
| **Output (L4)** | `summary` — Sync-Log/Status (gebucht/übersprungen/Duplikate) |
| **Dedup** | über bestehende AccountingBridge-Dedup-Logik |
| **Kunden** | konkreter SelectLine-Kunde; Muster für jedes weitere Umsystem |
| **Voraussetzungen (features-plan)** | SelectLine-Connector, `source`/`target`-Rolle auf Config, Integration-Nodes, ggf. kanonisches `Invoice`-Modell |
Zwei Kunden mit unterschiedlichem Kontenplan-Mapping = **zwei Solutions/Configs, ein Code**.
### S2 — «Periodisches Reporting» (Leit-Case: Pling Kaffee-Klatsch)
| | |
|---|---|
| **Bedürfnis** | Am 15./Monat aus 5 RMA-Buchhaltungen konsolidieren, 6 PDFs erzeugen, rollenbasiert mailen |
| **Trigger** | `trigger.schedule` `0 6 15 * *` (Europe/Zurich) + `trigger.manual` (rollen-beschränkt) |
| **Bausteine (Graph)** | `flow.loop`(5 Instanzen) → `trustee.refreshAccountingData``trustee.queryData` (Salden akt.+Vorjahr) → `data.consolidate` (sumByKey) → `ai.generateDocument`×6 (1 Holding + 5 Store) → `rbac.queryUsersByRole``outlook.send``file.create` (Archiv) |
| **Settings (L3)** | **Instanz-Set** (5 Stores), Konten-Ranges (Umsatz 30003999, Warenkosten 60006299, Personal 50005099), Cron, Empfänger-**Rollen** (Holding→`trustee-accountant`/`trustee-viewer`, Store→`trustee-client`, Protokoll→`trustee-admin`), `stopOnIncomplete` |
| **Output (L4)** | `file` — 6 PDFs, archiviert als `TrusteeDocument`; + `summary` Lauf-Protokoll |
| **Sonderfall** | Buchhaltung am 15. nicht abgeschlossen → durchlaufen mit Markierung (Conditional nach refresh), steuerbar via `stopOnIncomplete` |
| **Neutralisierung** | selektiv (Namen/Beschreibungen ja; Zahlen/Konten nein) |
| **Voraussetzungen (features-plan)** | `rbac.queryUsersByRole`, Trigger-`accessControl.requiredRoles`, `data.consolidate` (prüfen), `testMode` |
Vollständig spezifiziert (High-Level + Anhang); ~2 Wochen Build → bester End-to-End-Beleg der Solution-Schicht.
### S3 — «Dokumente verarbeiten + Antwort» (PWG Jahresmietzinsbestätigungen, 1.9c)
| | |
|---|---|
| **Bedürfnis** | Gescannte Rücklauf-Bestätigungen (≈3'200/Jahr) prüfen, Status klassifizieren, Antwortvorschläge |
| **Trigger** | `trigger.schedule` (täglich) oder `trigger.manual` |
| **Bausteine (Graph)** | `sharepoint.listFiles``flow.loop``sharepoint.downloadFile` + `trustee.extractFromFiles` (OCR) → `ai.prompt` (Scan vs. Abacus-Originaldaten, Status, Antwortvorschlag) → `data.writeToTable``email.send` |
| **Settings (L3)** | Scan-Ordner (SharePoint), Abacus-Mandant + Mietzins-Stammdaten-Abfrage, Empfänger (Sachbearbeiter), Prompt-Variante |
| **Output (L4)** | `table` — Übersicht verarbeiteter Bestätigungen (bestätigt / Abweichung / fehlende Unterschrift / unleserlich) + Mail-Zusammenfassung |
| **Kunden** | PWG (Pilot, Versand Sommer 2026, Deadline-gebunden) |
| **Voraussetzungen (features-plan)** | Prompt-Template «Mietzinsbestätigung prüfen», Abacus-Stammdaten-Abfrage konfigurieren, `data.writeToTable`-Output-Renderer |
### S4 — «Beleg-Import» (periodische Spesen-/Belegverarbeitung; 1.1, 1.10.5)
| | |
|---|---|
| **Bedürfnis** | Belege/Spesen aus SharePoint/Drive periodisch klassifizieren, kontieren, verbuchen |
| **Trigger** | `trigger.schedule` (z. B. täglich 22:00) |
| **Bausteine (Graph)** | `sharepoint.listFiles``flow.loop``trustee.extractFromFiles``trustee.processDocuments` (Klassifikation + Kontierung) → `trustee.syncToAccounting` |
| **Settings (L3)** | Quelle (Ordner), Ziel-Buchhaltung (RMA/Bexio/Abacus), Klassifikations-/Kontierungsoptionen, Zeitplan |
| **Output (L4)** | `table` verarbeitete Belege + `summary` |
| **Kunden** | Bling, PWG, Quid |
| **Voraussetzungen** | bestehende Pipeline + System-Template existiert bereits; als Solution kapseln |
### S5 — «Finanz-Analyse & Reporting» (1.21.7, 4.x — heute Prompt-Templates)
| | |
|---|---|
| **Bedürfnis** | Budget/Soll-Ist, KPI-Dashboard, Cashflow, Prognose, Jahresabschluss-Checks, Liquidität |
| **Trigger** | `trigger.manual` / `trigger.form` oder `trigger.schedule` (periodischer Report) |
| **Bausteine (Graph)** | `trustee.refreshAccountingData``trustee.queryData`/`aggregateTable` → `ai.generateDocument`/`ai.prompt` → Output |
| **Settings (L3)** | Periode(n), Vergleichsbasis (Vorjahr/Budget), optionaler Budget-Upload, KPI-Auswahl, Empfänger |
| **Output (L4)** | `table` (KPIs), `file` (Report-PDF) oder `summary` |
| **Kunden** | Bling, Quid, allgemein Treuhand |
| **Voraussetzungen** | bestehende Analyse-Prompt-Templates als Solution-Templates verfügbar machen (Migration aus `mainTrustee.py` → kuratierte Templates) |
### S6 — «Benachrichtigung / Report-Verteilung» (1.9.12, 4.5.8)
| | |
|---|---|
| **Bedürfnis** | Bei Ereignis/Zeitplan Bericht erzeugen und rollenbasiert verteilen; KPI-Alerts |
| **Trigger** | `trigger.schedule` / `trigger.event` (DB-Change → features-plan) |
| **Bausteine (Graph)** | Daten lesen → `ai.generateDocument` (optional) → `rbac.queryUsersByRole``email.send`/`outlook.send` |
| **Settings (L3)** | Auslöser/Schwellwerte, Empfänger-Rollen, Vorlage |
| **Output (L4)** | `summary` + Mail |
| **Voraussetzungen (features-plan)** | `rbac.queryUsersByRole`, optional `trigger.event`/DB-Change-Detection |
## Gemeinsames Settings-Muster (alle Solutions)
- **`settingsSchema`** automatisch aus `trigger.form` + exposed Node-Params abgeleitet (kuratierte Overrides später).
- **`settingsValues`** inkl. **Instanz-Set** (Multi-Instanz-Fan-out).
- **`triggerPolicy`** manuell/Zeitplan/Event/Form + `accessControl.requiredRoles` (bestehende Feature-Rollen).
- **`outputBinding.kind`** = `file | table | summary` (Dashboard später).
- **Lebenszyklus** in der «Lösungen»-Seite: Liste · Katalog/Neu (Vorlage oder AI) · Detail mit Tabs (Einstellungen · Testlauf · Läufe · Ausgabe).
## Betroffene Module
- **Daten/Config (kein Code pro Solution):** Solution-Definition + Settings-Record pro Feature-Instanz (Modell → features-plan), Workflow-Graph als Template/Version.
- **Kuratierte System-Templates:** `interfaces/interfaceBootstrap.py` — «Systeme synchronisieren», «Periodisches Reporting», «Dokumente verarbeiten», «Beleg-Import», «Finanz-Analyse».
- **Voraussetzungen (Code):** vollständig im **features-plan** (Solution-Schicht, generische Nodes, Connectors, `testMode`, `rbac.queryUsersByRole`).
- **Demo:** je Solution ein Demo-Setup (Pling-/PWG-/Bling-Mandant) — verweist auf Demo-Items aus dem alten Kundenplan.
## Entscheidungen
| Datum | Entscheidung | Begründung |
|-------|-------------|------------|
| 2026-06-04 | Kunden-Use-Cases primär als **Solutions** (Config) statt Code | step1-architecture Solution-first; skaliert ohne Engineering pro Kunde |
| 2026-06-04 | SelectLine→RMA und Pling als **erste produktive Solutions** | konkrete Geld-Cases, decken Sync- und Reporting-Muster ab |
| 2026-06-04 | Analyse-Prompt-Templates (Budget/KPI/Cashflow/…) werden **Solution-Templates** | bisher Trustee-interne Quick Actions → kundentauglich als Solutions |
| 2026-06-04 | Fehlende Bausteine werden **generisch** im features-plan gebaut, nie kundenspezifisch | «keine Kundenlogik im Code» |
## Umsetzungs-Checkliste
- [ ] Solution-Schicht + generische Bausteine verfügbar (→ features-plan: A1A3)
- [ ] System-Template «Systeme synchronisieren» + Demo SelectLine→RMA (S1)
- [ ] System-Template «Periodisches Reporting» + Pling-Solution konfiguriert (S2)
- [ ] System-Template «Dokumente verarbeiten» + PWG-Mietzins-Solution (S3) — Deadline Sommer 2026
- [ ] «Beleg-Import» als Solution kapseln (S4)
- [ ] Analyse-Templates → Solution-Templates migrieren (S5)
- [ ] «Benachrichtigung/Report» (S6) inkl. rollenbasierte Verteilung
- [ ] Pro Solution: Testlauf (`testMode`) grün, dann Aktivierung
## Akzeptanzkriterien
| # | Kriterium (Given-When-Then) | Prio |
|---|---|---|
| 1 | Given konfigurierte S1, When der Sync läuft, Then erscheinen SelectLine-Rechnungen als Buchungen in RMA (kein Kunden-Code; zweiter Kunde = nur andere Settings) | must |
| 2 | Given konfigurierte S2 (Pling), When der Monatslauf läuft, Then 6 PDFs erzeugt + rollenbasiert versendet + archiviert; manueller Start nur für `trustee-admin` | must |
| 3 | Given S2 im Testlauf, When ausgeführt, Then Reports werden erzeugt aber **keine** Mails versendet (`testMode`) | must |
| 4 | Given konfigurierte S3, When Scans eintreffen, Then Übersichtstabelle mit Status + Antwortvorschlägen + Mail | must |
| 5 | Given eine Solution, When der Kunde Settings ändert, Then ohne Code-Deploy wirksam (Settings = Daten) | must |
| 6 | Given ein neuer ähnlicher Use Case, When aus Template instanziiert, Then nur Settings nötig, kein Code | should |
## Offene Fragen
1. **S1 Erreichbarkeit:** SelectLine on-prem → Zugriffsweg (VPN/Tunnel/Agent)? Zielart RMA (AR-Rechnung vs. GL-Buchung)?
2. **S5 Migration:** Wie viele der Analyse-Prompt-Templates werden 1:1 Solution-Templates vs. konsolidiert?
3. **S2/S3 Output:** `outputBinding`-Detail (Artefakt-Referenz, `table`-Spalten aus Node-Output ableiten) — siehe step1-architecture «Output-Bindung».
4. **Demo-Daten:** welche Mandanten/Testdaten zuerst (Pling, PWG, Bling)?
## Links
- Architektur: `c-work/0-ideas/2026-06-CustomerCases-step1-architecture.md`
- Product Summary: `c-work/0-ideas/2026-06-CustomerCases-step2-communication-product-summary.md` (+ `.pdf`)
- Mockup: `c-work/0-ideas/2026-06-CustomerCases-step2-communication-mockup.html`
- Features/Code: `c-work/0-ideas/2026-06-CustomerCases-step3-features-plan.md`
- Pling-Spec: `pamocreate/projects/poweron/customer-pling/20-spezifikation/20260522-workflow-spec-kaffee-klatsch.md` (+ `-anhang.md`)
- Bausteine: `b-reference/platform-core/workflow.md`, `b-reference/platform-core/automation.md`, `b-reference/platform-core/features/trustee.md`
## Abschluss
- [ ] Bei Annahme → Solution-Templates + erste Konfigurationen in `c-work/2-build/`
- [ ] `b-reference/` Kanon-Seite «Solutions» nach Umsetzung
- [ ] `_CHANGELOG.md`-Eintrag pro Solution

View file

@ -1,195 +0,0 @@
<!-- status: plan -->
<!-- started: 2026-05-14 -->
<!-- component: gateway | ui-nyla | platform -->
# Lawyer Feature (Mandatsvorbereitung + Dashboards)
## Beschreibung und Kontext
Im Sales-Meeting mit David Vasella (WalderWyss) am 13.05.2026 hat sich ein klares Bild ergeben: Anwaltskanzleien arbeiten mit grossen Mengen **nicht human-readable Daten** (PDFs, E-Mails, frühere Mandate, Konflikt-Checks, KYC/AML, Buchungen). Zwischen internen Prozessen und der Mandantsbesprechung entsteht ein Overhead, den **Copilot nicht löst**. Existierende Branchen-Tools (Harvey.ai ~500 USD p/m/user, Legora, ClientFlex) sind teuer und decken die Anforderungen nicht voll ab. WW hat **kein CRM**.
PORTA hat bereits alle Bausteine: Workspace, Knowledge/RAG, Konnektoren, Neutralisierung, Private LLM. Das `lawyer`-Feature bündelt diese Bausteine zu einem **opinionated UI für Anwälte**: ein Feature-Modul mit zwei Hauptseiten **Dashboards** (HR / Business-Client / IT) und **Matter Preparation** (Mandatsvorbereitung in 5 Minuten).
Business-Treiber:
- WW konkretes Sales-Asset (HTML-Präsentation und später Live-Demo).
- Eigene Use Cases für Homepage (`www.poweron.swiss`) Sales-Story «echtes Produkt».
- Investor-Pitch (Founderful via Dominic + Philipp) braucht klare vertikale Geschichte.
- Wiederverwendbar für jede Anwaltskanzlei und mit Anpassung für Treuhand/Audit/Steuerberatung.
## Fokus und kritische Details
- **Berufsgeheimnis (StGB Art. 321)** Mandantsdaten dürfen den Mandanten-Tenant nicht verlassen. Neutralisierung + Private LLM **zwingend** für jeden Pfad, der LLM nutzt (`wiki/b-reference/platform/neutralization.md`).
- RBAC korrekt: feature-instance roles, **NICHT** mit mandate roles vermischen (`.cursor/rules/rbac-role-separation.mdc`).
- Daten kommen aus heterogenen Quellen: Document Management System (DMS), E-Mail-Archiv, Zeiterfassung, Buchhaltung, KYC/AML, Konflikt-Check-DB. Konnektor-Pflege ist der **harte Teil**, nicht das UI.
- Mockup-Daten in der WW-Präsentation müssen klar als **synthetic** markiert sein.
## Ziel und Nicht-Ziele
- **Ziel:** Feature-Modul `lawyer` mit:
- Dashboard-Seite mit Tabs pro Funktion (HR, Business/Client, IT, optional Finance).
- Matter-Preparation-Seite: Anwalt definiert Kontext (Mandant, Matter, Meeting-Ziel, Datum), System aggregiert Quellen, AI-Agent generiert Briefing (Kerndaten, Risiken, Deadlines, offene Punkte, Agenda-Vorschlag).
- **Ziel:** Wiederverwendung der bestehenden PORTA-Bausteine (Workspace, Knowledge, Konnektoren, Neutralisierung, Private LLM).
- **Ziel:** Standard-Konnektoren für DMS (SharePoint, iManage), E-Mail (Outlook/Exchange), KYC-/Konflikt-Datenquellen, Buchhaltung (im ersten Schritt einer pro Kategorie).
- **Explizit NICHT:** vollständiges Practice-Management-System ersetzen (kein Time-Tracking-Replacement, kein Billing-System).
- **Explizit NICHT:** generische Vertragsanalyse / Drafting (das machen Harvey/Legora besser, wir sind komplementär).
- **Explizit NICHT:** eigene KYC/AML-Datenquelle aufbauen wir konsumieren bestehende.
## Betroffene Module
- Gateway:
- Neues Feature-Modul `platform-core/modules/features/lawyer/` mit `mainLawyer.py`, `datamodelLawyer.py`, `interfaceLawyer.py`, `routeFeatureLawyer*.py`.
- Workflow-Method `platform-core/modules/workflows/methods/methodLawyer/` für `lawyer.prepareMatter`, `lawyer.queryData`.
- Konnektoren: prüfen, welche bestehen (`platform-core/modules/connectors/`), welche neu (DMS, KYC).
- Frontend:
- Neue Komponenten `ui-nyla/src/components/Lawyer/`.
- Dashboard-View mit Tabs.
- Matter-Preparation-View (analog Workspace, opinionated).
- DB-Migration: ja neue Tabellen `LawyerMatter`, `LawyerPreparation`, `LawyerDashboardSnapshot`, `LawyerKpi`.
- Andere Komponenten: Knowledge/RAG (bestehend), Neutralisierung (bestehend), Private LLM (bestehend), Workspace-Agent-Tools (Erweiterung).
## Entscheidungen
| Datum | Entscheidung | Begründung |
|-------|-------------|------------|
| 2026-05-14 | Feature-Code `lawyer` (analog `trustee`, `realEstate`) | Konsistenz mit bestehenden Feature-Modulen |
| 2026-05-14 | Template-Rollen `lawyer-admin`, `lawyer-user`, `lawyer-viewer` | RBAC-Regel: feature-instance roles, mandate-getrennt |
| 2026-05-14 | Matter-Preparation nutzt bestehenden Workspace-Agent + neue opinionated Tool-Chain | Wiederverwendung statt Neubau |
| 2026-05-14 | Dashboards starten als read-only Aggregations-Views auf Konnektor-Daten | Schneller Time-to-Demo, Schreibpfad später |
| 2026-05-14 | Sprache UI primär Englisch | WW-Audience Management Board, Investor-tauglich; DE-Lokalisierung Phase 2 |
## Use Cases (User Stories)
### UC-1: Matter Preparation in 5 Minutes
**Given** ein Anwalt hat morgen ein Klienten-Meeting für Matter `M-2024-0042` (M&A-Transaktion).
**When** er auf der Matter-Preparation-Seite den Matter und das Meeting-Ziel eingibt ("Statusbesprechung Due Diligence, offene Punkte"),
**Then** sammelt das System innerhalb von ~60 Sekunden aus DMS (alle Dokumente zu M-2024-0042), E-Mails (letzte 30 Tage), Zeiterfassung (WIP + Deadlines), KYC/AML (Aktueller Status), Konflikt-Check.
**And** generiert ein strukturiertes Briefing:
- Kerndaten Mandant + Matter
- Stand Due Diligence (Dokumente, offene Punkte)
- Risiken & Deadlines
- Offene Aktionen seit letzter Besprechung
- Vorschlag Agenda
- Quellenliste (jeder Punkt mit Link zur Quelle)
**And** alle Mandantsdaten werden neutralisiert, bevor sie das LLM erreichen.
### UC-2: Partner-Dashboard
**Given** ein Partner möchte vor der Wochensitzung den Stand seines Teams sehen.
**When** er die Dashboard-Seite öffnet,
**Then** sieht er HR-KPIs (Billable Hours, Utilization, Realization) für sein Team, Top-3-Risk-Matters, AR Aging.
**And** kann pro KPI in die Detailansicht drillen (Drilldown via Konnektor-Live-Query).
### UC-3: IT/Compliance-Dashboard
**Given** der IT-Leiter braucht für ein Audit-Meeting den Compliance-Status.
**When** er den IT-Tab öffnet,
**Then** sieht er Uptime, Security-Incidents (letzte 90 Tage), Patch-Status, KYC/AML-Backlog, Conflict-Check-SLAs.
## Datenmodell-Skizze
| Modell | Felder (Kern) | Kommentar |
|--------|---------------|-----------|
| `LawyerMatter` | id, featureInstanceId, mandateCode, clientName, matterType, openedAt, status, leadLawyerUserId | Mandate spiegeln, nicht zweimal halten |
| `LawyerPreparation` | id, matterId, requestedBy, meetingGoal, createdAt, briefingJson, sourceRefs | Persistiert das generierte Briefing für Audit + Wiederverwendung |
| `LawyerDashboardSnapshot` | id, featureInstanceId, dashboardType, periodStart, periodEnd, dataJson, generatedAt | Cache für Dashboard-Daten, Refresh periodisch |
| `LawyerKpi` | id, featureInstanceId, kpiCode, label, formula, lastValue, lastValueAt, dashboardType | Konfigurierbare KPI-Definitionen pro Tenant |
| `LawyerSourceMap` | id, featureInstanceId, sourceType, connectorRef, mappingJson | Welcher Konnektor liefert welche Daten in welche KPI |
## Actions (Workflow-Method)
| Action | Eingabe | Output | Zweck |
|--------|---------|--------|-------|
| `lawyer.prepareMatter` | featureInstanceId, matterId, meetingGoal, lookbackDays | LawyerPreparation (briefingJson + sourceRefs) | Sammelt aus Quellen, neutralisiert, generiert Briefing via Workspace-Agent |
| `lawyer.refreshDashboard` | featureInstanceId, dashboardType, periodStart, periodEnd | LawyerDashboardSnapshot | Re-aggregiert KPI-Werte aus Konnektoren |
| `lawyer.queryData` | featureInstanceId, freie Filter | ActionResult mit Query-Resultat | Read-only Zugriff für AI-Agent (analog `trustee.queryData`) |
## UI-Skizze
```
/lawyer/<featureInstanceId>/
├── dashboards/
│ ├── hr (Tab)
│ ├── business (Tab)
│ ├── it (Tab)
│ └── finance (Tab, optional)
└── matter-preparation/
├── <list of recent matters>
└── <matterId>/
├── briefing (generated)
├── sources (drilldown)
└── agenda-export (PDF/Markdown)
```
## RBAC-Mapping
- Template-Rollen (Feature-Code `lawyer`, `mandateId=NULL`, `isSystemRole=False`):
- `lawyer-admin` Feature-Instance-Admin, Konnektor-Konfig, KPI-Definition.
- `lawyer-user` Anwalt, Matter-Preparation, Dashboard read.
- `lawyer-viewer` Read-only, z. B. Management Board.
- Nutzung: `FeatureAccessRole` mit `featureCode=lawyer, featureInstanceId=<id>, mandateId=<id>, roleId=<>`.
- Strikt getrennt von Mandate-Rollen (`admin`, `user`, `viewer`).
## Umsetzungs-Checkliste
- [ ] Datenmodell (`datamodelLawyer.py`) 5 Modelle + PowerOnModel-Basis
- [ ] Migration: Auto-Schema reicht? (analog `trustee`)
- [ ] Feature-Modul (`mainLawyer.py`) inkl. Template-Rollen-Definition
- [ ] Workflow-Method `methodLawyer/` mit 3 Actions
- [ ] Konnektoren-Inventur: was haben wir, was fehlt
- [ ] DMS-Konnektor (SharePoint vorhanden, iManage neu?)
- [ ] E-Mail-Konnektor (Outlook/Exchange vorhanden?)
- [ ] Zeiterfassung (mandantenabhängig, Anbindung über generisches Schema)
- [ ] KYC/AML (extern, API-Anbindung mandantenspezifisch)
- [ ] Konflikt-Check (intern WW-System API klären)
- [ ] Routes (`routeFeatureLawyer.py`)
- [ ] Frontend-Komponenten (`Lawyer/Dashboard`, `Lawyer/MatterPreparation`)
- [ ] RBAC: Template-Rollen registrieren (siehe `.cursor/rules/rbac-role-separation.mdc`)
- [ ] Neutralisierung: `prepareMatter`-Action zwingend mit `PrivateLLM`-Pfad für sensitive Daten
- [ ] Navigation (Gateway → Frontend) Feature-Eintrag
- [ ] Billing-Impact: prüfen (analog andere Features pro Feature-Instance, Subscription-Capacity)
- [ ] Mockup-Daten-Set (synthetic) für WW-Präsentation + Demo
- [ ] Demo-Login-Mandant einrichten (für Live-Demo nach Präsentation)
## Akzeptanzkriterien
| # | Kriterium (Given-When-Then) | Prio |
|---|---------------------------|------|
| 1 | Given Anwalt mit `lawyer-user`-Rolle, When er Matter-Preparation für offenen Matter triggert, Then erhält er in <90s strukturiertes Briefing mit 3 Quellen | must |
| 2 | Given sensitive Mandantsdaten (Namen, Beträge), When `lawyer.prepareMatter` läuft, Then werden alle PII vor LLM-Call neutralisiert (Audit-Trail in Neutralization-Log) | must |
| 3 | Given User mit `lawyer-viewer`, When er Dashboard öffnet, Then sieht er KPIs read-only ohne Schreib-Buttons | must |
| 4 | Given User mit Mandate-Rolle `admin` aber ohne `lawyer-*`, When er Lawyer-Feature öffnet, Then Access Denied | must |
| 5 | Given Dashboard-Konnektor offline, When `refreshDashboard` läuft, Then Snapshot zeigt Fehlerstatus, Frontend zeigt klare Meldung statt leerer Werte | should |
| 6 | Given Briefing generiert, When Anwalt es exportiert, Then PDF/Markdown mit Quellenliste und «synthetic data» Wasserzeichen (im Demo-Mandanten) | should |
## Testplan
| ID | AC | Art | Automatisiert | Repo-Pfad | Status |
|----|----|-----|--------------|-----------|--------|
| T1 | 1 | api | ja | platform-core/tests/test_lawyer_prepare_matter.py | pending |
| T2 | 2 | integration | ja | platform-core/tests/test_lawyer_neutralization.py | pending |
| T3 | 3,4 | api | ja | platform-core/tests/test_lawyer_rbac.py | pending |
| T4 | 5 | integration | ja | platform-core/tests/test_lawyer_dashboard_refresh.py | pending |
| T5 | 1,6 | e2e | manuell | | pending |
## Demo-Asset Plan (für WW-Präsentation)
- Synthetic Matter `M-DEMO-001` (M&A) mit fiktiven Dokumenten, E-Mails, Zeiteinträgen.
- Briefing-Output statisch generiert und in `30-presentation/src/data/matter-preparation.json` ablegen, damit die HTML-Präsentation **ohne Backend** funktioniert.
- Wenn David Live-Demo will: gleichen Demo-Mandanten im PORTA-Demo-Tenant live verfügbar machen.
## Links
- WW-Kontext: `pamocreate/projects/poweron/customer-walderwyss/20-objectives/20260514-zusammenfassung-meeting-dv.md`
- WW-Präsentation: `pamocreate/projects/poweron/customer-walderwyss/30-presentation/`
- Bestehende Feature-Doku als Vorbild: `wiki/b-reference/platform-core/features/trustee.md`
- Plattform-Bausteine: `wiki/b-reference/platform/neutralization.md`, `wiki/b-reference/platform/rbac.md`
- PR: (noch nicht)
- Issue: (noch nicht)
## Abschluss
- [ ] `b-reference/platform-core/features/lawyer.md` als neue Kanon-Seite anlegen
- [ ] `TOPICS.md` Eintrag für Lawyer-Feature
- [ ] Dieses Dokument → `2-build/``3-validate/``4-done/`
- [ ] Eintrag in `c-work/_CHANGELOG.md` pro Phase

View file

@ -1,222 +0,0 @@
<!-- status: plan -->
<!-- started: 2026-06-04 -->
<!-- component: gateway | ui-nyla | platform -->
# Umsystem-Integration: generische Connectors + kundenspezifische Workflows + Datenquellen-Seiten
## Beschreibung und Kontext
Ein Kunde schreibt seine Rechnungen in einem externen System (**SelectLine**, REST-API vorhanden) und möchte, dass diese Rechnungen **ins RMA (Run My Accounts)** geladen werden. Die Frage des Kunden: «Kann PowerOn dafür einfach eine Schnittstelle machen?»
Der konkrete Fall ist ein Spezialfall eines generischen Musters: PowerOn soll **proprietäre Umsysteme** (ERP, Fakturierung, Lohn, …) anbinden. Wir haben die Logik dafür im Prinzip schon im Feature **Trustee** sind Buchhaltungssysteme (ABACUS, Bexio, Banana, **RMA**) über das **AccountingBridge-Connector-Framework** angebunden (`platform-core/modules/features/trustee/accounting/`). RMA ist bereits ein vollwertiger Ziel-Connector (inkl. `pushBooking`, `pushInvoice`, Beleg-Upload).
**Kern-Architekturvorgabe (Auftrag):** Es soll **keine kundenspezifische Logik im Code** entstehen. Wir trennen sauber in:
1. **Generische Bausteine** (Code, wiederverwendbar, ohne Kundennamen): Connectors, kanonische Datenmodelle, generische Workflow-Nodes.
2. **Kundenspezifische Logik** (als **Daten** = Workflow-Graph + Config, nicht als Code): die konkrete Verdrahtung «SelectLine → Mapping → RMA» pro Mandant/Instanz im Graphical Editor.
Business-Treiber:
- Konkreter Kundenwunsch (Termin nächste Woche).
- Wiederverwendbares Muster für jedes weitere Umsystem → Sales-Asset und skalierbare Onboarding-Story.
- Vermeidung von Wartungs-Hölle durch `if kunde == X`-Code.
**Abgrenzung — NICHT als Personal Source einbinden.** Personal Sources (UDB-`DataSource`-Familie: SharePoint, Drive, Infomaniak) sind **user-privat** und für **unstrukturierte RAG-Daten** gedacht (`wiki/b-reference/platform/unified-data-bar.md`). Eine Debitorenrechnung von SelectLine nach RMA ist ein **transaktionaler Buchungs-Vorgang auf Mandant-/Feature-Ebene** mit Dedup, Sync-Audit und verschlüsselten Credentials pro Mandant. Das gehört in das **Trustee-Connector-Framework** (`featureInstanceId`-scoped), nicht in Personal Sources.
## Fokus und kritische Details
- **Trennung Baustein ↔ Kundenlogik ist das eigentliche Ziel.** Jede Versuchung, Kunden-/Systemspezifika fest zu verdrahten (Konten-Mappings, Filter, Belegart-Auswahl), muss in **Config/Workflow-Graph** wandern, nicht in den Connector.
- **Connector = reiner API-Adapter.** Auth, Lesen/Schreiben von Ressourcen, Mapping zwischen nativem API-Format und kanonischem Modell. Keine Geschäftsregeln, keine Kundennamen, keine Konto-Zuordnungen.
- **Richtung.** Bestehende AccountingBridge ist heute **push-orientiert** (lokale `TrusteePosition` → extern). SelectLine ist eine **Quelle** (lesen). Wir brauchen einen sauberen **Import-/Source-Pfad** und eine **Rolle** (`source` / `target`) auf der Config, weil eine Instanz künftig *eine Quelle* **und** *ein Ziel* hat.
- **On-Prem-Erreichbarkeit (grösstes Risiko, extern abhängig).** Die SelectLine-API läuft typischerweise beim Kunden (Doku zeigt `http://localhost/...`). Unsere Cloud muss sie erreichen → VPN / Reverse-Tunnel / fester Endpoint / On-Site-Agent. Klärt Aufwand und Sicherheit.
- **Datenschutz/Neutralisierung.** Rechnungen enthalten Personendaten. Pfade, die durch das LLM laufen (z. B. KI-gestütztes Konten-Mapping), müssen über das Neutralisierungs-Gate (`wiki/b-reference/platform/neutralization.md`).
- **Fragile Stellen:** `accountingBridge.py` (Orchestrierung, Dedup, Sync-Records) ist heute auf Position→Push zugeschnitten; der Source-Pfad muss additiv ergänzt werden, ohne den bestehenden Push-Pfad zu brechen. `TrusteeAccountingConfig` erlaubt heute nur **eine aktive** Config pro Instanz (siehe `getActiveConfig`).
## Ziel und Nicht-Ziele
- **Ziel:** Generisches, plugin-basiertes **Umsystem-Connector-Framework** (Erweiterung des bestehenden AccountingBridge-Musters), mit dem ein neues System = **eine Connector-Datei + Config**, ohne Architekturänderung.
- **Ziel:** **SelectLine-Connector** (Quelle): Login, Lesen von Ausgangsrechnungen (`Document`/`DocumentKind`), Kunden, Konten, Steuerschlüssel.
- **Ziel:** **Source→Target-Import** als **generische Workflow-Nodes**, sodass «SelectLine → RMA» ein **Workflow-Graph** ist (kundenspezifisch als Daten), kein Code.
- **Ziel:** **UI-Muster «Datenquelle = Seite»** im Feature Trustee: die Seite «Buchhaltungssystem» existiert; das Muster wird generisch, sodass weitere Kategorien (z. B. «Saläre», «Fakturierung») als eigene Seiten dazukommen können.
- **Explizit NICHT:** kundenspezifische Logik im Code (`if kunde == …`).
- **Explizit NICHT:** SelectLine als Personal Source.
- **Explizit NICHT:** Aufbau eines eigenen ERP/Faktura-Systems wir konsumieren/transferieren nur.
- **Explizit NICHT (vorerst):** voll generisches «Integrations-Framework für alles». Wir bleiben im Trustee-Kontext und verallgemeinern erst, wenn die zweite Kategorie (Saläre) real wird (YAGNI siehe «Meine Gedanken»).
## Architektur: generische Bausteine vs. kundenspezifische Logik
Vier Schichten. Schicht 13 sind **Code (generisch)**, Schicht 4 ist **Daten (kundenspezifisch)**.
```
┌─ Schicht 4: WORKFLOW-GRAPH + CONFIG (Daten, pro Instanz, im Graphical Editor) ─┐
│ "SelectLine → mappe Konto 1100→1100, Belegart=AR, seit lastSync → RMA (GL)" │
│ Konto-Mappings · Filter · Zeitplan · Quelle/Ziel-Auswahl → KUNDENSPEZIFISCH │
└─────────────────────────────────────────────────────────────────────────────────┘
▲ konsumiert generische Nodes, enthält KEINEN Code
┌─ Schicht 3: WORKFLOW-NODES (generische Typed Actions) ─────────────────────────┐
│ source.fetchInvoices · transform.mapAccounts · target.pushBooking · attachDoc │
└─────────────────────────────────────────────────────────────────────────────────┘
▲ arbeiten ausschliesslich auf kanonischen Modellen
┌─ Schicht 2: KANONISCHE MODELLE ─────────────────────────────────────────────────┐
│ AccountingBooking / AccountingBookingLine / Invoice / Contact / Chart … │
│ (bereits vorhanden in accountingConnectorBase.py) │
└─────────────────────────────────────────────────────────────────────────────────┘
▲ Connectors übersetzen natives API-Format ⇄ kanonisch
┌─ Schicht 1: CONNECTORS (generische API-Adapter, plugin-discovery) ─────────────┐
│ accountingConnectorRma.py · accountingConnectorSelectline.py · …bexio/abacus │
│ nur Auth + Lesen/Schreiben + Mapping. KEINE Kundenlogik. │
└─────────────────────────────────────────────────────────────────────────────────┘
```
### Schicht 1 — Connectors (neu: SelectLine)
- Neue Datei `platform-core/modules/features/trustee/accounting/connectors/accountingConnectorSelectline.py`, implementiert `BaseAccountingConnector` (`accountingConnectorBase.py`). Auto-Discovery über `accountingRegistry.py` (Pattern `accountingConnector*.py`) → **keine Registrierungs-Änderung nötig**.
- Methoden: `testConnection` (Login + GET), `getChartOfAccounts` (Konten), `getCustomers`/`getVendors`, und die Lese-Seite für Belege (siehe «Source-Capability» unten).
- Config-Felder (`getRequiredConfigFields`): `baseUrl`, `username`, `password` (secret), optional `mandant`. Verschlüsselt wie alle Configs (`_decryptConfig`).
- **Source-Capability:** Da die Base heute primär Push/Read-Journal kennt, ergänzen wir eine schlanke, optionale Lesemethode für Belege, z. B. `getOutgoingInvoices(config, dateFrom, sinceCursor) -> List[Invoice]` (Default `[]` in der Base; nur Source-Connectors überschreiben). Alternativ Wiederverwendung von `getJournalEntries` Entscheidung siehe «Offene Fragen».
### Schicht 2 — kanonische Modelle (vorhanden)
`AccountingBooking`, `AccountingBookingLine`, `AccountingChart`, `SyncResult` etc. in `accountingConnectorBase.py`. Für reine Debitoren-Fakturen ggf. ein kanonisches `Invoice`-Modell ergänzen (Header + Lines + Kunde + Steuer), falls RMA als **AR-Rechnung** (offener Posten) statt GL-Buchung beschrieben werden soll.
### Schicht 3 — Workflow-Nodes (generisch, Typed Actions)
Analog zu den bestehenden Trustee-Actions (`trustee.extractFromFiles` → `processDocuments``syncToAccounting`). Neue, **system-agnostische** Nodes:
- `integration.fetchFromSource` — zieht Belege/Buchungen aus dem **konfigurierten Quell-Connector** (Quelle = Config, nicht hartcodiert) → kanonische Liste.
- `integration.mapAccounts` — wendet eine **Mapping-Tabelle** (Config/Daten) auf Konten/Steuercodes an.
- `integration.pushToTarget` — schreibt über den **konfigurierten Ziel-Connector** (`pushBooking`/`pushInvoice` + Beleg-Upload, bereits in RMA vorhanden).
Diese Nodes erscheinen über den Editor-Adapter (`graphicalEditor/nodeDefinitions/`) als Bausteine im Graphical Editor. Die Pipeline `trigger → fetchFromSource(SelectLine) → mapAccounts → pushToTarget(RMA)` ersetzt damit für strukturierte Quellen den KI-Extraktionsschritt (günstiger + zuverlässiger).
### Schicht 4 — Workflow-Graph + Config (kundenspezifisch, als Daten)
- Der konkrete Kundenfluss ist ein **Workflow-Template/Graph** pro Feature-Instanz (persistiert), gebaut im Graphical Editor. Konten-Mappings, Filter (nur Ausgangsrechnungen, nur «seit letztem Sync»), Buchungsart, Zeitplan = **Config-Datensätze**.
- Ergebnis: zwei Kunden mit SelectLine→RMA, aber unterschiedlichem Kontenplan-Mapping = **zwei Graphen/Configs, ein Code**.
### Datenmodell-Änderung
`TrusteeAccountingConfig` um **`role`** (`source` | `target`) erweitern, sodass pro Instanz mehrere Connector-Configs koexistieren (eine Quelle + ein Ziel). `getActiveConfig` / `_resolveConnectorAndConfig` entsprechend um `role` filtern. Optional: `connectorCategory` (`accounting` | `payroll` | `invoicing`) für die UI-Seitenzuordnung.
## SelectLine-API Befund (Kurz)
Geprüft anhand hilfe.selectline.ch und der Demo-API (demo.slmobile.de):
- REST, JSON/XML. Auth: `POST /Login` mit `{username,password}``AccessToken`/`LoginId`; danach Header `Authorization: LoginId <token>` (Session-Token, Re-Login bei Ablauf).
- Relevante Ressourcen: **`Document` / `DocumentKind`** (Belegkette inkl. Ausgangsrechnungen), `Customers`/`Vendors` (Geschäftspartner), `Konten` + `Kontensalden`, `Journale`, `Offene Posten`, `Steuerschlüssel`, `Kostenrechnung`, `Bankassistent` (camt.053-Import).
- Betriebsmodell: i. d. R. **on-premise** beim Kunden → Erreichbarkeit klären (Risiko oben).
- Swagger-/OpenAPI-Beschreibung pro Installation herunterladbar → exaktes Beleg-Schema beim Kunden verifizieren.
## UI-Konzept: «Datenquelle = Seite»
Heute ist «Buchhaltungs-Einstellungen» eine eigene Seite im Trustee-Feature:
- Registriert als UI-Object `ui.feature.trustee.settings` (`meta.area="settings"`, `admin_only`) in `mainTrustee.py`.
- Gemappt auf `TrusteeAccountingSettingsView` in `ui-nyla/src/pages/FeatureView.tsx` (`VIEW_COMPONENTS.trustee.settings`).
- Innen bereits Tabs: «Verbindungseinstellungen» + «Buchhaltungsdaten importieren» (Connector wählen → Credentials → Test → Import).
**Vorschlag:** dieses Muster zu einem **generischen «Datenquellen-Seiten»-Pattern** verallgemeinern eine Seite pro **Kategorie** von Umsystem:
| Seite (UI-Area) | Kategorie | Connectors (Beispiele) | Kanonisches Modell |
|---|---|---|---|
| Buchhaltungssystem (existiert) | `accounting` | RMA, Bexio, Abacus, **SelectLine (Quelle)** | AccountingBooking |
| **Saläre** (Idee) | `payroll` | SwissSalary, Abacus Lohn, Swissdec-konform | PayrollEntry (neu) |
| Fakturierung (Idee) | `invoicing` | SelectLine, Bexio | Invoice |
Pro Seite identischer Aufbau (**eine generische React-Komponente, parametrisiert über `category`**):
1. **Verbindungen** — Connectors der Kategorie listen, Rolle (Quelle/Ziel) wählen, Credentials, Test (wiederverwendet die bestehende `TrusteeAccountingSettingsView`-Mechanik, generalisiert).
2. **Datenfluss/Import** — Workflow-Template wählen/starten (= Schicht-4-Graph), Zeitplan, Status/Audit.
3. **Daten** — eingelesene Datensätze (read-only Spiegel).
Konkret:
- Generische `IntegrationSettingsView` (aus `TrusteeAccountingSettingsView` extrahiert), die `category` als Prop bekommt.
- Neue UI-Areas in `mainTrustee.py` (z. B. `ui.feature.trustee.payroll`) + Mapping in `FeatureView.tsx`**gleiche** Komponente, andere `category`.
- «Saläre» ist bewusst **nur ein Platzhalter-Beispiel**, um zu zeigen, dass das Muster skaliert; nicht Teil der ersten Umsetzung.
## Betroffene Module
- **Gateway (platform-core):**
- `features/trustee/accounting/connectors/accountingConnectorSelectline.py` (neu).
- `accounting/accountingConnectorBase.py` (optionale Source-Lesemethode, Default `[]`).
- `accounting/accountingBridge.py` (additiver Import-/Source-Pfad; `role`-Auflösung).
- `datamodelFeatureTrustee.py` (`TrusteeAccountingConfig.role` [+ optional `connectorCategory`]) → **DB-Migration: ja**.
- `workflows/methods/methodTrustee/actions/` + `graphicalEditor/nodeDefinitions/` (generische Nodes `integration.fetchFromSource` / `mapAccounts` / `pushToTarget`).
- `mainTrustee.py` (UI-Areas, RBAC-Objekte, Workflow-Templates).
- **Frontend (ui-nyla):**
- `TrusteeAccountingSettingsView` → generische `IntegrationSettingsView` (`category`-Prop).
- `FeatureView.tsx` Registry + `mainTrustee` UI-Areas für weitere Seiten.
- `trusteeApi.ts` (Connector-Listing nach Kategorie, Rolle source/target).
- **DB-Migration:** ja (`role`, optional `connectorCategory`).
- **Andere:** Neutralisierung (falls KI-Mapping), Audit/Billing (Sync-Volumen).
## Entscheidungen
| Datum | Entscheidung | Begründung |
|-------|-------------|------------|
| 2026-06-04 | Umsystem als Trustee-Connector, **nicht** als Personal Source | Transaktional, mandant-scoped, Dedup/Audit/verschlüsselte Credentials bereits in AccountingBridge |
| 2026-06-04 | Kundenlogik als Workflow-Graph + Config, nicht im Code | Auftrag: keine kundenspezifische Logik im Code; nutzt bestehende Typed-Action-/Editor-Architektur |
| 2026-06-04 | UI-Muster «Datenquelle = Seite» pro Kategorie, eine generische Komponente | Skaliert auf Saläre/Fakturierung ohne Copy-Paste |
## Umsetzungs-Checkliste
- [ ] DB: `TrusteeAccountingConfig.role` (+ optional `connectorCategory`) + Migration
- [ ] Bridge: Source-Auflösung nach `role`, Import-Pfad (additiv, Push-Pfad unverändert)
- [ ] Connector: `accountingConnectorSelectline.py` (Login/Test/Konten/Kunden/Belege lesen)
- [ ] Kanonisch: `Invoice`-Modell prüfen/ergänzen (falls AR-Rechnung in RMA)
- [ ] Workflow-Nodes: `integration.fetchFromSource` / `mapAccounts` / `pushToTarget` + Editor-Adapter
- [ ] Workflow-Template «Source→Target Import» (parametrisierbar)
- [ ] UI: `IntegrationSettingsView` generalisieren (`category`), Quelle/Ziel-Auswahl
- [ ] RBAC / Permissions (neue UI-Areas, admin_only)
- [ ] Neutralisierung betroffen? (nur falls KI-Mapping)
- [ ] Navigation / Routing (UI-Areas + FeatureView-Registry)
- [ ] Billing-Impact? (Sync-Läufe/Volumen)
## Akzeptanzkriterien
| # | Kriterium (Given-When-Then) | Prio |
|---|---------------------------|------|
| 1 | Given konfigurierter SelectLine-Source + RMA-Target, When der Import-Workflow läuft, Then erscheinen die SelectLine-Ausgangsrechnungen als Buchungen in RMA (inkl. Beleg-Verlinkung) | must |
| 2 | Given zwei Mandanten mit unterschiedlichem Konten-Mapping, When beide SelectLine→RMA nutzen, Then unterscheiden sie sich nur in Workflow-Graph/Config **kein** kundenspezifischer Code | must |
| 3 | Given ein neues Umsystem, When ein Connector-File + Config ergänzt wird, Then ist es ohne Änderung an Registry/Bridge/Editor verfügbar | must |
| 4 | Given erneuter Import, When Belege bereits gebucht sind, Then werden sie über die bestehende Dedup-Logik nicht doppelt gebucht | must |
| 5 | Given das UI-Muster, When eine neue Kategorie-Seite («Saläre») registriert wird, Then nutzt sie dieselbe generische Komponente | should |
## Testplan
| ID | AC | Art | Automatisiert | Repo-Pfad | Status |
|----|----|-----|--------------|-----------|--------|
| T1 | 1 | unit | ja | platform-core/tests/unit/features/trustee/test_accountingConnectorSelectline.py | pending |
| T2 | 1,4 | integration | ja | platform-core/tests/integration/trustee/test_source_target_import_e2e.py | pending |
| T3 | 3 | unit | ja | platform-core/tests/unit/.../test_adapter_validator.py (Editor-Node-Drift) | pending |
| T4 | 2 | unit | ja | platform-core/tests/unit/.../test_integration_nodes.py (Mapping aus Config) | pending |
## Offene Fragen (für den Kundentermin)
1. **Erreichbarkeit:** Wo läuft die SelectLine-API (on-prem/Cloud)? Welcher Zugriffsweg (VPN/Tunnel/Agent)?
2. **Zielart in RMA:** Debitoren-Rechnung (AR, offener Posten) **oder** GL-Buchung? → bestimmt `pushInvoice`-Ausbau vs. `pushBooking`.
3. **Mapping:** Liefert SelectLine pro Rechnung Konto + Steuerschlüssel, oder Kontenplan-Mapping SelectLine→RMA nötig?
4. **Beleg-PDF:** Rechnungs-PDF mit nach RMA (Beleg-Upload vorhanden)?
5. **Delta/Frequenz:** On-demand, Zeitplan oder Event? Cursor = Belegnummer/Datum?
6. **Alternative:** SelectLine `Bankassistent` (camt.053) relevant oder nur Ausgangsrechnungen?
## Meine Gedanken / Empfehlungen
- **Saubere Trennung ist erreichbar, weil die Plattform sie schon vorlebt.** Trustee nutzt bereits Typed Actions + Graphical Editor + Templates. «Kundenlogik als Graph» ist kein neues Paradigma, sondern Anwendung des Bestehenden. Das ist der grösste Hebel gegen kundenspezifischen Code.
- **Nicht zu früh über-generalisieren.** Ein einziges «BaseConnector für alles» mit Capability-Mixins (`AccountingCapable`, `PayrollCapable`) ist elegant, aber bevor «Saläre» real ist, würde ich beim bestehenden `BaseAccountingConnector` bleiben und nur die **Source-Rolle** ergänzen. Die Abstraktion ziehen wir, wenn die zweite Kategorie konkret wird sonst bauen wir ein Framework für hypothetische Fälle (YAGNI).
- **Namensgebung zur Abgrenzung:** «Personal Sources» = user-privat/RAG. Diese hier sind **«Umsystem-Anbindungen» / «Integrationen»** auf Mandant-Ebene. Klare Begriffe verhindern, dass die zwei Welten wieder vermischt werden.
- **Source vs. Target ist die wichtigste neue Achse.** Sie macht aus dem heutigen Push-Framework ein bidirektionales Integrations-Framework und ist die Voraussetzung für «System A → PowerOn → System B» generell.
- **«Saläre»-Seite** ist ein gutes nächstes Beispiel: Lohnsystem (Swissdec-konform) → Lohnbuchungen → Buchhaltung. Gleicher Mechanismus, neues kanonisches Modell `PayrollEntry`. Bestätigt, dass das Seiten-Muster trägt.
- **Risiko bleibt extern:** On-Prem-Erreichbarkeit von SelectLine ist der kritische Pfad das ist eher Infrastruktur/Netzwerk als Code. Im Kundentermin zuerst klären.
## Links
- Vorgelagerte Analyse (dieser Chat): SelectLine-API-Prüfung + erste Empfehlung
- Referenz Trustee: `wiki/b-reference/platform-core/features/trustee.md`
- Referenz UDB/Personal Sources: `wiki/b-reference/platform/unified-data-bar.md`
- Code: `platform-core/modules/features/trustee/accounting/` (Bridge, Base, Registry, Connectors)
- PR: —
- Issue: —
## Abschluss
- [ ] b-reference/ aktualisiert (`features/trustee.md` Abschnitt «Source-Connectors / Integrationen»; ggf. neue `platform/integrations.md`)
- [ ] TOPICS.md aktualisiert (neues Thema «Umsystem-Integrationen»)
- [ ] Dieses Dokument → c-work/2-build/ (bei Umsetzungsbeginn), am Ende → z-archive/

View file

@ -14,6 +14,9 @@ Skip: reine Refactors, Formatting, Lint, Dep-Bumps, Test-only, Wiki-Tippfehler.
## 2026-06-04
- 2026-06-04 | docs | wiki | **CustomerCases-Doks auf einheitliche Naming-Convention umbenannt**: `2026-06-STEP*`-Dateien → `2026-06-CustomerCases-stepN-*` (step1=architecture, step2=communication [product-summary md/pdf + mockup html], step3=solutions-plan/features-plan). Alle Cross-Referenzen in den Dokumenten + Changelog-Pfade angepasst. (c-work: c-work/0-ideas/2026-06-CustomerCases-step1-architecture.md u. a.)
- 2026-06-04 | docs | wiki | **STEP2-Pläne neu strukturiert: Solutions vs. Features**: Die drei bisherigen STEP2-Docs (lawyer-feature, pm-consolidated-customer-requirements, umsystem-integration) durch zwei architektur-konforme Pläne ersetzt. `step3-solutions-plan.md` = alle konfigurierten Use Cases als Solutions (S1 SelectLine→RMA, S2 Pling-Reporting, S3 PWG-Mietzins, S4 Beleg-Import, S5 Finanz-Analysen, S6 Notification) mit Trigger/Bausteine/Settings/Output je Solution + Klassifikationstabelle. `step3-features-plan.md` = der Code dahinter (Teil A Plattform-Enabler: Solution-Schicht L3/L4, generische Nodes rbac.queryUsersByRole/testMode/integration.*, Connectors; Teil B vertikale Features: lawyer, commcoach, trustee-core). (c-work: c-work/0-ideas/2026-06-CustomerCases-step3-solutions-plan.md, 2026-06-CustomerCases-step3-features-plan.md)
- 2026-06-04 | docs | wiki | **Konzept: Solution-Schicht (Customer Workflows) + Pling-Use-Case**: Architektur-Idee fuer generische L3/L4-Solution-Schicht ueber dem Workflow-Stack (Use Case → konfigurierter Workflow, kein Kunden-Code). Pling «Kaffee-Klatsch» Monatsreporting als staerkstes Validierungsbeispiel eingearbeitet (Multi-Instanz-Fan-out, rollenbasierte Verteilung). Plus generische Product-Summary und klickbares HTML-Mockup im ui-nyla-Look. (c-work: c-work/0-ideas/2026-06-CustomerCases-step1-architecture.md, 2026-06-CustomerCases-step2-communication-product-summary.md, 2026-06-CustomerCases-step2-communication-mockup.html)
- 2026-06-04 | docs | wiki | **Plan: Umsystem-Integration (Connectors + Workflows + Datenquellen-Seiten)**: Arbeitsdokument fuer generische Umsystem-Anbindung (SelectLine→RMA als Pilot). Trennung generische Bausteine (Connectors/kanonische Modelle/Workflow-Nodes) vs. kundenspezifische Logik (Workflow-Graph + Config). UI-Muster «Datenquelle = Seite» pro Kategorie (Buchhaltung existiert, Saläre als Idee). (c-work: c-work/1-plan/2026-06-umsystem-integration-connectors-und-datenquellen-seiten.md)
## 2026-06-03