diff --git a/c-work/1-plan/2026-06-umsystem-integration-connectors-und-datenquellen-seiten.md b/c-work/1-plan/2026-06-umsystem-integration-connectors-und-datenquellen-seiten.md new file mode 100644 index 0000000..aea6b23 --- /dev/null +++ b/c-work/1-plan/2026-06-umsystem-integration-connectors-und-datenquellen-seiten.md @@ -0,0 +1,222 @@ + + + + +# 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 1–3 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 ` (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/ diff --git a/c-work/_CHANGELOG.md b/c-work/_CHANGELOG.md index f2cbecf..55e4679 100644 --- a/c-work/_CHANGELOG.md +++ b/c-work/_CHANGELOG.md @@ -12,6 +12,10 @@ type: `feat` `fix` `refactor` `docs` `test` `chore` `build` · scope: `platfor Skip: reine Refactors, Formatting, Lint, Dep-Bumps, Test-only, Wiki-Tippfehler. +## 2026-06-04 + +- 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 - 2026-06-03 | fix | platform-core | **Image MIME-Type Pre-Validation in Extraction Pipeline**: Unsupported Bild-Formate (image/bmp, image/tiff, image/x-icon etc.) werden jetzt VOR dem Failover-Loop erkannt und uebersprungen. Magic-Bytes-Sniffing korrigiert falsche MIME-Types. Verhindert 6000+ Error-Storm bei EML-Verarbeitung (vorher: jedes unsupported Bild x 10+ Models = 30+ API-Errors). Safety-Net auch in aicorePluginAnthropic. diff --git a/d-guides/deployment/poweron-sec.kdbx b/d-guides/deployment/poweron-sec.kdbx index ed7be6d..8227f66 100644 Binary files a/d-guides/deployment/poweron-sec.kdbx and b/d-guides/deployment/poweron-sec.kdbx differ