This commit is contained in:
ValueOn AG 2026-04-26 08:36:33 +02:00
parent 9ae1952843
commit 24190f532a
8 changed files with 3043 additions and 12 deletions

View file

@ -1,5 +1,5 @@
<!-- status: canonical -->
<!-- lastReviewed: 2026-04-06 -->
<!-- lastReviewed: 2026-04-25 -->
# PowerOn PORTA -- Dokumentation
@ -44,6 +44,8 @@ PowerOn PORTA ist eine Multi-Tenant SaaS-Plattform mit Feature-Store-Modell, AI-
**Kernregel:** Während Planung, Umsetzung und Testing pflegst du **nur** das eine Arbeits-Dokument in `c-work/`. Kanon-Seiten in `b-reference/` und `TOPICS.md` werden erst am Ende aktualisiert.
**Nach jedem Change:** 1 Zeile in [`c-work/_CHANGELOG.md`](c-work/_CHANGELOG.md) (Format dort beschrieben).
---
## b-reference/ Aufbau

View file

@ -1,6 +1,6 @@
<!-- status: canonical -->
<!-- lastReviewed: 2026-04-24 -->
<!-- verifiedAgainst: gateway/modules/workflows/methods/methodTrustee/ + gateway/modules/features/trustee/ + Typed Action Architecture Phasen 1-5 -->
<!-- lastReviewed: 2026-04-25 -->
<!-- verifiedAgainst: gateway/modules/workflows/methods/methodTrustee/ + gateway/modules/features/trustee/ + Typed Action Architecture Phasen 1-5 + Account-Balance-Import -->
# Feature: Trustee
@ -107,6 +107,20 @@ trigger.manual -> trustee.extractFromFiles -> trustee.processDocuments -> truste
`trustee.refreshAccountingData` ruft `AccountingBridge.fetchSnapshots` -- die Tabellen `TrusteeDataAccount`, `TrusteeDataJournal*`, `TrusteeDataContact`, `TrusteeDataAccountBalance` werden read-only befuellt.
### Saldenliste (`TrusteeDataAccountBalance`)
Die Tabelle `TrusteeDataAccountBalance` enthaelt pro Konto + Periode (13 Buckets: Annual `periodMonth=0` + 12 Monate) einen Datensatz mit `openingBalance`, `debitTotal`, `creditTotal`, `closingBalance`.
**Datenquelle (Prioritaet):**
1. **Connector** (`getAccountBalances`): Jeder Accounting-Connector kann ueber die optionale Methode `BaseAccountingConnector.getAccountBalances(config, years, accountNumbers)` echte Salden liefern. `AccountingPeriodBalance` (Pydantic) ist der einheitliche Rueckgabetyp.
- **RMA**: Dedizierter Endpunkt `GET /gl/saldo` -- liefert den echten, durch RMA berechneten Schlusssaldo inkl. Vorjahresvortrag und Jahresabschluss-Buchungen. Pro Konto + Stichtag ein API-Call. Wildcard-Pattern (`xxxx`, `xxxxx`) aus Kontenplan abgeleitet fuer Bulk-Abfrage.
- **Bexio**: Kein Saldo-Endpunkt verfuegbar; Aggregation aus `GET /3.0/accounting/journal` mit korrekter kumulativer Berechnung (Bilanzkonten 1xxx-2xxx carry-over, Erfolgskonten 3xxx-9xxx jaehrlicher Reset).
- **Abacus**: Aggregation aus `GET GeneralJournalEntries` (OData V4). Code-Hinweis fuer optionale `AccountBalances`-Entity (instanzabhaengig).
2. **Lokaler Fallback** (`_buildLocalBalanceFallback`): Wenn der Connector `[]` zurueckgibt (kein Endpunkt oder Fehler), aggregiert `accountingDataSync` die bereits importierten `TrusteeDataJournalLine`-Zeilen kumulativ. `openingBalance` der ersten Periode = `0` (kein Vortrag aus fehlenden Daten erfindbar).
Quelle wird im Log pro Sync dokumentiert: `source=connector` bzw. `source=local-fallback`.
---
## REST-Endpunkte (Auswahl)
@ -134,6 +148,10 @@ UI-Sichtbarkeit der Daten-Tabellen-Seite haengt am Permission-Eintrag `ui.featur
| FeatureInstanceRef | `gateway/tests/unit/workflows/test_featureInstanceRefMigration.py` | Materialisierung + Auto-Unwrap, Idempotenz. |
| Live-E2E | `gateway/tests/integration/trustee/test_spesenbelege_workflow_e2e.py` | `executeGraph` durch `processDocuments + syncToAccounting` mit In-Memory-Fakes. |
| DB-CLI | `gateway/tests/unit/scripts/test_migrate_feature_instance_refs.py` | Dry-run + Live-Migration des persistierten Graphs. |
| Balance RMA | `gateway/tests/unit/features/trustee/test_accountingConnectorRma_balances.py` | `getAccountBalances` via gemocktem `/gl/saldo` (BuHa-SoHa-Szenario + ER-Reset). |
| Balance Bexio | `gateway/tests/unit/features/trustee/test_accountingConnectorBexio_balances.py` | Kumulative Aggregation aus Journal (BS carry-over + ER-Reset). |
| Balance Abacus | `gateway/tests/unit/features/trustee/test_accountingConnectorAbacus_balances.py` | OData-Aggregation (BS carry-over + ER-Reset). |
| Balance Sync | `gateway/tests/unit/features/trustee/test_accountingDataSync_balances.py` | Connector-Pfad (verbatim persist) + Local-Fallback (kumulative Berechnung). |
---
@ -142,3 +160,4 @@ UI-Sichtbarkeit der Daten-Tabellen-Seite haengt am Permission-Eintrag `ui.featur
- Architektur-Plan: [`wiki/c-work/3-validate/2026-04-typed-action-architecture.md`](../../../c-work/3-validate/2026-04-typed-action-architecture.md)
- Folge-Plan: [`wiki/c-work/1-plan/2026-04-typed-action-followups.md`](../../../c-work/1-plan/2026-04-typed-action-followups.md)
- Adapter-Drift-Backlog (abgeschlossen): [`wiki/c-work/4-done/2026-04-adapter-drift-cleanup.md`](../../../c-work/4-done/2026-04-adapter-drift-cleanup.md)
- Account-Balance-Import (abgeschlossen): [`wiki/c-work/4-done/2026-04-trustee-account-balances-import.md`](../../../c-work/4-done/2026-04-trustee-account-balances-import.md)

View file

@ -0,0 +1,172 @@
<!-- status: done -->
<!-- lastUpdated: 2026-04-25 -->
<!-- lastReviewed: 2026-04-25 -->
<!-- owner: ai-agent -->
<!-- related: z-archive/c-work/2026-04-node-typization-audit.md, c-work/4-done/2026-04-typed-action-architecture.md, c-work/4-done/2026-04-typed-action-followups.md -->
# FeatureInstanceRef-Adapter-Migration & Graph-Editor UI-Cleanup (2026-04-25)
> Restbestand aus dem Node-Typisierungs-Audit (jetzt z-archiv).
> Ziel: keine `frontendType: "hidden"` Pflichtfelder mehr, klare UI-Texte,
> theme-konformer DataPicker, optionale Schema-Ansicht fur Sysadmins.
## Auslosender Befund
Bei der Audit-Umsetzung wurde die _strukturelle_ Korrektur (PORT_TYPE_CATALOG /
Typed Action Architecture) durchgezogen — die _Anwendung_ in den
`nodeDefinitions/*.py` jedoch nur teilweise. Trustee + Redmine fuhren
weiter `featureInstanceId: string, hidden, required=True`, was im Editor
zu **Phantom-Pflichtfeldern** ("Pflichtfelder ohne Quelle: Trustee Feature-
Instanz-ID"), unklarer Fehler-Banner und einem nicht-bedienbaren Knoten
fuhrt.
Zusatzlich zeigte der Screenshot 2026-04-25 zwei UI-Probleme die unabhangig
mitgenommen werden:
- DataPicker-Modal mit nicht lesbaren Farb-Kombinationen
- "Schema (Typ-Referenz)" und ausschweifende `description`-Texte
(`erarbeitete Dokumentenliste eines Upstream-Producers …`) in der
End-User-View
## Anpassungs-Liste (zum Abhaken)
### A. Audit archiviert ✅
- [x] `wiki/c-work/1-plan/2026-04-node-typization-audit.md` ->
`wiki/z-archive/c-work/2026-04-node-typization-audit.md`
- [x] Forward-Link auf Typed Action Architecture + dieses Track-Doc
- [x] Changelog-Eintrag
### B. Backend — `featureInstanceId` typisieren
#### B1. Neuer Frontend-Type + Endpoint
- [x] `routeFeatureGraphicalEditor.py`: neuer Endpoint
`GET /api/workflows/{instanceId}/options/feature.instance?featureCode=<code>&enabledOnly=true`
- Antwort: `{ options: [{ value: "<id>", label: "<label> ([code])" }] }`
- Auflosung uber `getRootInterface().getFeatureInstancesByMandate(mandateId, enabledOnly=True)`
- Filter `featureCode` Pflicht (sonst 400, sonst Datenflut)
- [x] `_LEGACY_RENDERERS_THAT_HANDLE_BINDINGS` (`NodeConfigPanel.tsx`) erweitert: `'featureInstance'`
#### B2. Trustee-Nodes (5 Stuck) — `gateway/.../nodeDefinitions/trustee.py`
| Node | aktuell | neu |
|-------------------------------------|--------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------|
| `trustee.refreshAccountingData` | `featureInstanceId: string, hidden, required` | `featureInstanceId: FeatureInstanceRef[trustee], frontendType: featureInstance, frontendOptions: {featureCode: trustee}` |
| `trustee.extractFromFiles` | dito | dito |
| `trustee.processDocuments` | dito; `documentList` description aufraumen (Dev-Justifikation) | dito + description = `t("Dokumentenliste — gebunden via DataRef.")` |
| `trustee.syncToAccounting` | dito; `documentList` ebenfalls | dito |
| `trustee.queryData` | dito | dito |
Alle 5 Nodes umgesetzt via wiederverwendbarem `_TRUSTEE_INSTANCE_PARAM`-Dict
(siehe `trustee.py`). Bestaetigt durch
`tests/unit/graphicalEditor/test_featureInstanceRef_node_definitions.py`.
#### B3. Redmine-Nodes (6 Stuck) — `gateway/.../nodeDefinitions/redmine.py`
- [x] `redmine.readTicket`
- [x] `redmine.listTickets`
- [x] `redmine.createTicket`
- [x] `redmine.updateTicket`
- [x] `redmine.getStats`
- [x] `redmine.runSync`
Alle 6 via `_REDMINE_INSTANCE_PARAM`-Dict, `featureInstanceId` ->
`FeatureInstanceRef[redmine]` mit
`frontendType: "featureInstance", frontendOptions: {"featureCode": "redmine"}`.
#### B4. Beobachtete `frontendType: hidden`-Restbestande (out-of-scope, in
2026-05 oder eigenem Track-Doc adressieren — hier nur dokumentiert)
| Datei | Param | Typ aktuell | Anmerkung |
|------------------|----------------|-------------|-----------------------------------------------------------------|
| `ai.py` | `documentList` | `string` | Korrekt: ueber `dataRef` gebunden, `string` lugt nur den DataPicker |
| `email.py` | `documentList`, `emailContent` | `string` | dito |
| `sharepoint.py` | `content` | `string` | dito |
| `clickup.py` | `content` | `string` | dito |
| `context.py` | `documentList` | `string` | dito |
| `file.py` | `context` | `string` | dito |
> Diese Faelle sind _nicht_ Phantom-Pflichtfelder (sie sind
> entweder optional oder werden korrekt via DataRef gebunden), losen aber
> die "Schema (Typ-Referenz)"-Verwirrung mit aus. Strukturell sind sie
> Kandidaten fur `frontendType: "dataRef"` mit prazisem `type:
> "List[ActionDocument]"` etc. — eigene Iteration.
### C. Frontend — Renderer & Safety Net
- [x] `FeatureInstancePicker.tsx` (Modell: `ConnectionPicker`):
- Lade `/api/workflows/{instanceId}/options/feature.instance?featureCode=<code>`
- 0 Ergebnisse: Hinweis _"Keine {code}-Instanz im aktiven Mandanten — bitte in der Admin-Konsole anlegen."_
- 1 Ergebnis: Auto-Pick (`autoSingleRef`-Guard)
- N Ergebnisse: `<select>` mit Default-Option `"{code}-Mandant wählen"`
- [x] `frontendTypeRenderers/index.tsx`:
- Import + Eintrag in `FRONTEND_TYPE_RENDERERS`: `featureInstance: FeatureInstancePicker`
- Eintrag in `_LEGACY_RENDERERS_THAT_HANDLE_BINDINGS` (im `NodeConfigPanel.tsx`-Set)
- [x] **Safety Net direkt in `paramValidation.ts/findRequiredErrors`**:
hidden-Pflicht-Parameter werden zentral gefiltert, damit Banner,
FlowCanvas-Badges und Run-Button-`blockedReason` synchron bleiben.
Zusatzlich `_shouldUseRequiredPicker` (`NodeConfigPanel.tsx`) liefert
fruh `false` fur `frontendType === 'hidden'` und die Render-Schleife
uberspringt die Zeile komplett (`return null`).
### D. Editor-Verbose-Toggle (Issue 1)
- [x] `CanvasHeader.tsx`:
- Sysadmin-Check via `getUserDataCache()?.isSysAdmin === true`
- Checkbox _"Schema-Details"_ rechts neben Workspace-Button,
nur wenn Sysadmin (gestrichelter Rahmen, Tooltip mit Erklaerung)
- Wert in `localStorage('flowEditor.verboseSchema')`
- [x] `Automation2FlowEditor.tsx`: `verboseSchema` state + persist-effekt,
als Prop runtergereicht an `CanvasHeader` und `NodeConfigPanel`
- [x] `NodeConfigPanel.tsx`: `<details>`-Block "Schema (Typ-Referenz, Sysadmin-
Ansicht)" und Parameter-Typ-Badges nur, wenn `verboseSchema === true`.
PortField-Liste + Header-Spans zusatzlich auf CSS-Variablen umgestellt.
### E. DataPicker-Theming (Issue 3)
- [x] `DataPicker.tsx`: alle hardcoded Farben (`#555`, `#888`, `#999`, `#666`)
-> CSS-Variablen (`var(--text-secondary)`, `var(--text-tertiary)`,
`var(--bg-secondary)`, `var(--border-color)`)
- [x] Inline-Tags (`expectedParamType`-Badge, "Nur kompatible"-Label,
Schema-Hint, Type-Hint hinter Leaves) auf CSS-Klassen
`dataPickerLeafType`, `dataPickerNodeSchemaHint` umgezogen
- [x] `Automation2FlowEditor.module.css`:
- Hover-Safety-Net `.dataPickerLeaf:hover * { color: inherit; }`
keine grauen Type-Hints mehr auf blauem Hover-Hintergrund
- Neue `.dataPickerLeafType`, `.dataPickerNodeSchemaHint`,
`.dataPickerIterateBtn` mit theme-konformen Variablen
### F. Banner-Klartext (Issue 4)
- [x] `NodeConfigPanel.tsx`: Banner _"Pflichtfelder ohne Quelle"_ zeigt
jetzt `param.name` (kurze Maschinenkennung), die volle Beschreibung
hangt als mehrzeiliger `title=`-Tooltip am Banner
- [x] `RequiredAttributePicker.tsx`: nutzt `getLabel(param.description)`
bereits korrekt; Justifikationen (`erarbeitete Dokumentenliste …`) sind
fortan nur noch eine Datenfrage in den `nodeDefinitions` und betreffen
diesen Banner nicht mehr (description-Saeuberung in B2/B3 erledigt)
### G. Tests
- [x] `gateway/tests/unit/graphicalEditor/test_featureInstanceRef_node_definitions.py`:
parametrized fuer alle Trustee+Redmine-Nodes — Typ ist
`FeatureInstanceRef[<code>]`, frontendType `featureInstance`,
`frontendOptions.featureCode` korrekt; plus Regression-Guard gegen
Re-Einfuehrung der `string + hidden`-Form (13 Testfaelle)
- [x] `gateway/tests/unit/graphicalEditor/test_route_options_feature_instance.py`:
Smoke-Test, dass der Endpoint `GET /api/workflows/{instanceId}/options/feature.instance`
registriert ist und `featureCode` Pflicht ist (2 Testfaelle)
- [x] `frontend_nyla/.../paramValidation.test.ts`: neuer Fall
_"skips required params with frontendType='hidden' (UI safety net)"_
- [ ] (Optional, Folge-Iteration) FeatureInstancePicker.test.tsx mit msw
fur 0/1/N-Antworten; aktuell durch das Renderer-Pattern abgedeckt
(ConnectionPicker hat dasselbe Modell, dort existieren Smoke-Tests)
### H. Wrap-up
- [x] Track-Doc nach `c-work/4-done/` verschieben
- [x] Eintrag in `c-work/_CHANGELOG.md`
- [ ] (Folge-Aufgabe) `b-reference/gateway/workflow.md` um Abschnitt
_"FeatureInstanceRef adapter binding"_ erweitern; eigenes Mini-Track
oder bei naechster Workflow-Doku-Iteration mitnehmen

View file

@ -0,0 +1,238 @@
<!-- status: done -->
<!-- started: 2026-04-25 -->
<!-- completed: 2026-04-25 -->
<!-- component: gateway -->
# Trustee: Echte Schlusssalden aus Buchhaltungssystem importieren
## Beschreibung und Kontext
**Bug-Report Kunde (PROD-Mandant `BuHa SoHa`, Connector RMA):** Fragt man Nyla
nach dem Banksaldo per 31.12.2025 (Konto 1020), antwortet sie mit
`CHF 79'939.86`. Der echte Schlusssaldo ist `CHF 48'507.41`. Auch alle daraus
abgeleiteten Auswertungen (Geldflussrechnung, Umsatz-Diagramme, Plausichecks)
sind dadurch falsch.
**Root cause:** Die Tabelle `TrusteeDataAccountBalance` wird nicht aus dem
Buchhaltungssystem importiert, sondern in `accountingDataSync._persistBalances`
lokal aus den Journalzeilen aggregiert -- mit drei eigenstaendigen Fehlern:
1. `closingBalance = debit - credit` **nur** aus den Buchungen der jeweiligen
Periode (Monat oder Jahres-Bucket). Das ist die Periodenbewegung, kein
Schlusssaldo. Schon innerhalb desselben Jahres summieren sich die Vormonate
nicht auf den Stichtag.
2. `openingBalance` ist hart auf `0.0` kodiert -- der Saldovortrag aus den
Vorjahren / vor dem Importfenster fehlt komplett.
3. Auch der Jahres-Bucket `(accNo, year, 0)` laeuft durch dieselbe Formel,
d.h. der "Jahres-Schlusssaldo" ist eigentlich nur die Jahres-Bewegung.
**Architekturloch:** `BaseAccountingConnector` kennt schlicht keine
`getAccountBalances`-Methode. Der Defekt trifft alle drei aktuell registrierten
Connectoren (RMA / Bexio / Abacus).
**Warum jetzt:** Das Trustee-Feature steht im aktiven Roll-out beim Pilot-Kunden
(`BuHa SoHa`, Customer Trustee Demo). Falsche Saldenzahlen unterminieren das
Vertrauen in die ganze Plattform und blockieren saemtliche AI-Auswertungen, die
auf Salden aufbauen (Geldfluss, Plausichecks, Bilanz-/ER-Vergleiche).
**Risiko bei Verzicht:** Jede Frage an den Agenten zu Salden / Bilanzpositionen
liefert subtile Falschwerte (kein offensichtlicher Crash, sondern stillschweigend
falsche Zahlen). Auditor-Risiko.
## Fokus und kritische Details
- **RMA hat einen dedizierten Saldo-Endpunkt** (`GET /gl/saldo` mit `accno`,
`from`, `to`, `bookkeeping_main_curr`, `exclude_yearend_bookings`). Liefert
pro Konto den echten, durch RMA berechneten Schlusssaldo unter
Beruecksichtigung von Vorjahres-Vortraegen und Jahresabschluss-Buchungen.
**Quelle der Wahrheit ist immer der Connector**, nicht eine lokale
Berechnung -- Letztere kann Vortraege und Jahresabschluss-Offsets nicht
rekonstruieren, wenn das Importfenster nur einen Teil der Historie enthaelt.
- **Bexio + Abacus haben keinen entsprechenden Endpunkt** in dem Detailgrad.
Bexio liefert `GET /3.0/accounting/journal` (alle Journal-Eintraege mit
`debit_account_id`, `credit_account_id`, `amount`, `date`); Abacus
`GET GeneralJournalEntries` (OData V4). Dort muessen wir lokal
**kumulativ** rechnen und den **Vorjahres-Vortrag** explizit aus den
Journal-Daten ableiten (Eroeffnungsbuchungen am Geschaeftsjahres-Anfang
bzw. Abschluss-Buchungen am Vorjahres-Ende).
- **Datenmodell `TrusteeDataAccountBalance` bleibt unveraendert** -- die
Felder `openingBalance`, `debitTotal`, `creditTotal`, `closingBalance` sind
bereits vorhanden. Der Bug ist rein in der Befuellung; kein DB-Migration
noetig (`_bulkClear` + `_bulkCreate` ueberschreibt jeden Sync ohnehin).
- **Konsumenten** der Tabelle: `mainTrustee.DATA_OBJECTS`,
`routeFeatureTrustee` (data-tables UI), `methodTrustee/actions/queryData`
(entity=`balances`, mode=`raw`/`aggregate`), AI-Agent ueber
`/api/automation2/catalog`. Keine Schema-Aenderung, also kein Frontend-Impact.
- **Persistenz-Performance**: Wir reden von 200--500 Konten x 13 Perioden
(Annual + 12 Monate) = max ~6500 Rows pro Sync. Der bestehende
`_bulkCreate`-Pfad ist dafuer dimensioniert (vgl. accountingDataSync.py
Header-Kommentar zur Asyncio-Architektur).
- **Connector-Fallback-Vertrag**: Wenn `getAccountBalances` `[]`
zurueckgibt **und** keine Exception wirft, gilt das als "Connector kann
das nicht / hat nichts geliefert" -- in dem Fall faellt der Sync auf
die korrigierte lokale Aggregation zurueck. Wirft der Connector eine
Exception, wird sie in `summary["errors"]` aufgenommen und der Sync laeuft
weiter (gleiches Pattern wie bei den uebrigen Phasen).
- **i18n**: Keine neuen User-facing Strings.
- **Naming**: Funktionen `_`-Prefix fuer intern (`_buildBalanceUrl`,
`_aggregateBalancesFromLines`); camelCase ueberall (Python + TS).
- **Logging**: Keine Emojis (vgl. `.cursor/rules/python-coding.mdc`).
## Ziel und Nicht-Ziele
- **Ziel**: `TrusteeDataAccountBalance` enthaelt **echte** Salden aus dem
Buchhaltungssystem (RMA, soweit verfuegbar) bzw. eine korrekt **kumulierte**
lokale Berechnung (Bexio, Abacus). `closingBalance` = Stichtagsbestand,
`openingBalance` = Stand zu Periodenbeginn, inkl. Vortraege.
- **Ziel**: Erweiterung von `BaseAccountingConnector` um optionale Methode
`getAccountBalances(...)`. Default-Implementierung gibt `[]` zurueck (keine
externe Quelle) -- Sync faellt auf den korrigierten Fallback zurueck.
- **Ziel**: RMA-Connector implementiert echte Saldenabfrage; Bexio + Abacus
bekommen entweder eine voll funktionsfaehige `getAccountBalances`-
Implementierung oder, falls nicht moeglich, einen detaillierten Code-
Kommentar mit Endpunkt-Recherche und Skizze des fehlenden Stuecks
(User-Direktive: "besser gleich umsetzen bei allen 3").
- **Ziel**: Korrekter Fallback in `_persistBalances`: Wenn der Connector
nichts liefert, **kumuliere** Journal-Lines pro Konto chronologisch und
fuelle `openingBalance` aus den Vorjahresbuchungen (oder `0`, wenn das
Importfenster den Account-Lifecycle abdeckt).
- **Ziel**: Unit-Test pro Connector + Integrationstest, der den BuHa-SoHa-
Fall reproduziert (Konto mit Vortrag, mehreren Monaten Bewegungen,
korrekter Schlusssaldo Ende Dezember).
- **Explizit NICHT**: Schema- oder DB-Migration. Felder existieren bereits;
jeder Sync schreibt die Tabelle ohnehin neu (`_bulkClear`).
- **Explizit NICHT**: Aenderung am Frontend (data-tables-Seite). Die
Tabelle bekommt nur korrekte Werte -- die Spalten sind bereits da.
- **Explizit NICHT**: Aenderung am AI-Agent / `queryData`-Action. Die Action
liefert weiter `entity="balances"` aus derselben Tabelle.
- **Explizit NICHT**: Saldo-Logik ausserhalb von Trustee (Sanctions-Plattform
etc.).
## Betroffene Module
- **Gateway**:
- `gateway/modules/features/trustee/accounting/accountingConnectorBase.py`
-- neue Datenklasse `AccountingPeriodBalance`, neue optionale Methode
`getAccountBalances`.
- `gateway/modules/features/trustee/accounting/connectors/accountingConnectorRma.py`
-- `getAccountBalances` via `GET /gl/saldo`. Annual-Bucket + 12 Monats-
Buckets, jeweils kumulativ bis Periodenende. Opening-Balance = Saldo per
Periodenstart - 1 Tag (zweiter API-Call) oder via vorheriger Periode.
- `gateway/modules/features/trustee/accounting/connectors/accountingConnectorBexio.py`
-- `getAccountBalances` aggregiert lokal aus `GET /3.0/accounting/journal`
(filtert per `from`/`to`-Param) -- Bexio bietet keine Saldoliste.
- `gateway/modules/features/trustee/accounting/connectors/accountingConnectorAbacus.py`
-- `getAccountBalances` aggregiert lokal aus `GET GeneralJournalEntries`
(OData-Filter `JournalDate ge ... and le ...`). Mit Schemahinweis im Code,
falls Abacus-Instanz die Entity `AccountBalances` (offiziell vorhanden,
aber Verfuegbarkeit instanzabhaengig) ausliefern kann.
- `gateway/modules/features/trustee/accounting/accountingDataSync.py`
-- Phase 4 (`_persistBalances`) umbauen: zuerst Connector fragen; bei
leerer / fehlerhafter Antwort den **korrigierten** lokalen Fallback nutzen.
- `gateway/modules/workflows/methods/methodTrustee/actions/refreshAccountingData.py`
-- nur Doc-String anpassen (verweist auf neuen Datenfluss).
- **Frontend**: keine Aenderung.
- **DB-Migration**: nein.
- **Andere Komponenten**: keine.
## Entscheidungen
| Datum | Entscheidung | Begruendung |
|-------|-------------|------------|
| 2026-04-25 | Connector-Werte haben Vorrang, lokale Aggregation ist Fallback. | Vorjahres-Vortraege und Jahresabschluss-Offsets kann nur das Buchhaltungssystem zuverlaessig liefern; lokale Aggregation aus dem Importfenster bleibt naehrungsweise. |
| 2026-04-25 | Per Konto + Periode 13 Buckets (Annual + 12 Monate). Jeder Bucket = Schlusssaldo per Periodenende. | Konsistent mit bestehendem Datenmodell und der `BuHa SoHa`-Tabelle (Monat 12 = Dezember-Stichtag). Annual-Bucket = Schlusssaldo per Geschaeftsjahres-Ende. |
| 2026-04-25 | RMA: Echte Saldenabfrage via `/gl/saldo` pro Periode (Annual + 12 Monate). 13 sequenzielle GETs pro Sync. | RMA-API bietet pro Aufruf nur einen Stichtag; mehrere Aufrufe sind unkritisch (Sync laeuft im Hintergrund, schon heute 30+s). |
| 2026-04-25 | Bexio: Aggregation aus `/3.0/accounting/journal` (kein dedizierter Saldo-Endpunkt vorhanden). | Bexio Journal-API liefert alle benoetigten Felder; lokale Kumulation ist hier exakt, weil der Bexio-Mandant typischerweise im Importfenster komplett liegt. |
| 2026-04-25 | Abacus: Aggregation aus `GeneralJournalEntries`. Falls Instanz `AccountBalances`-Entity hat, kann sie spaeter bevorzugt werden (Code-Kommentar fuer Folge-Iteration). | OData-Schema variiert pro Abacus-Instanz; sichere Default-Strategie ist Aggregation. |
| 2026-04-25 | `AccountingPeriodBalance`-Pydantic-Modell (statt dict) fuer Connector-Output. | Konsistent mit `AccountingChart`, `AccountingBooking`; Typsicherheit + Pydantic-Validierung. |
| 2026-04-25 | `getAccountBalances` ist OPTIONAL (Default: `[]`). | Erlaubt graduelles Rollout pro Connector ohne Breaking Change; bestehender Fallback bleibt verfuegbar. |
| 2026-04-25 | Lokaler Fallback rechnet jetzt korrekt kumulativ pro Konto, sortiert Journal-Lines nach Buchungsdatum, und propagiert den Saldo Monat-fuer-Monat. `openingBalance` der ersten Periode = `0` (besser nichts als ein erfundener Wert). | Vortrags-Berechnung ohne Connector-Daten ist nicht zuverlaessig; explizites `openingBalance=0` + Kommentar im UI/Doku ist ehrlicher. |
## Umsetzungs-Checkliste
### Backend
- [x] `AccountingPeriodBalance` (Pydantic) in `accountingConnectorBase.py`:
Felder `accountNumber`, `periodYear`, `periodMonth`, `openingBalance`,
`debitTotal`, `creditTotal`, `closingBalance`, `currency`, `asOfDate`.
- [x] `BaseAccountingConnector.getAccountBalances(config, year, accountNumbers=None)`
mit Default-Implementierung `return []`. Doc-String dokumentiert
Vertrag (Annual-Bucket = `periodMonth=0`).
- [x] RMA: `getAccountBalances` via `GET /gl/saldo`. Pro Konto-Filter `accno`
(z.B. `xxxx`) und Datum `to=YYYY-MM-DD`, einmal pro Periode (Annual +
12 Monate). Monatlicher `openingBalance` = Schlusssaldo Vormonat.
Fehler / leere Antwort -> Konto skippen (nicht Sync abbrechen).
- [x] Bexio: `getAccountBalances` ueber `_loadRawAccounts` (Account-Map)
+ `GET /3.0/accounting/journal?from=YYYY-MM-DD&to=YYYY-MM-DD`. Lokale
Kumulation (debit - credit) pro Konto pro Monat. Jahres-Bucket separat.
- [x] Abacus: `getAccountBalances` ueber `GET GeneralJournalEntries`
mit OData-Filter; gleiche Aggregations-Logik. Code-Kommentar mit
Hinweis auf optionale `AccountBalances`-Entity (instanzabhaengig).
- [x] `accountingDataSync._persistBalances` umbauen:
1. `await connector.getAccountBalances(plainConfig, year=...)` aufrufen
(Jahre aus dateFrom/dateTo ableiten -- kann ueber mehrere Jahre gehen).
2. Bei nicht-leerer Antwort: direkt persistieren.
3. Sonst Fallback `_aggregateBalancesFromLines(...)` -- korrekt kumulativ.
- [x] Logging: pro Phase eindeutige Log-Zeile mit Connector-Name + Source
(`buha` / `local-fallback`) + Zeilenzahl.
### Tests
- [x] `gateway/tests/unit/features/trustee/test_accountingConnectorRma_balances.py`:
`getAccountBalances` mit gemocktem `/gl/saldo` (17 Tests: BuHa-SoHa-Szenario,
ER-Reset, Parser, Helpers).
- [x] `gateway/tests/unit/features/trustee/test_accountingConnectorBexio_balances.py`:
lokale Aggregation aus gemockter Journal-Liste (8 Tests: BS cumulative,
carry-over, ER-Reset).
- [x] `gateway/tests/unit/features/trustee/test_accountingConnectorAbacus_balances.py`:
OData-Aggregation (6 Tests: BS carry-over, ER-Reset).
- [x] `gateway/tests/unit/features/trustee/test_accountingDataSync_balances.py`:
End-to-End mit FakeDb (11 Tests: Connector-Path verbatim persist,
Local-Fallback kumulative BS/ER-Berechnung, _resolveBalanceYears,
_isIncomeStatementAccount).
### Wiki
- [x] Plan: dieses Dokument von `1-plan/` -> `4-done/` verschoben.
- [x] `wiki/c-work/_CHANGELOG.md`: 2 Zeilen (fix + test).
- [x] `wiki/b-reference/gateway/features/trustee.md`: Abschnitt
"Saldenliste (`TrusteeDataAccountBalance`)" mit Datenquelle + Fallback
ergaenzt; Tests-Tabelle erweitert; Link auf dieses Dokument.
- [x] `lastReviewed: 2026-04-25` + `verifiedAgainst: ... + Account-Balance-Import`
aktualisiert.
## Akzeptanzkriterien
| # | Kriterium (Given-When-Then) | Prio |
|---|---------------------------|------|
| 1 | Given Mandant `BuHa SoHa` mit RMA-Connector und Konto 1020 (echter Schlusssaldo per 31.12.2025 = `48'507.41`), When der Sync laeuft, Then enthaelt `TrusteeDataAccountBalance` fuer `accountNumber='1020'`, `periodYear=2025`, `periodMonth=12` einen `closingBalance = 48'507.41` (Toleranz +/- 0.01 CHF). | must |
| 2 | Given derselbe Sync, When man die Annual-Zeile abfragt (`periodMonth=0`), Then `closingBalance` = Schlusssaldo per Geschaeftsjahres-Ende (= `48'507.41` bei Kalenderjahr-Mandant). | must |
| 3 | Given derselbe Sync, When man die Zeile fuer `periodMonth=11` abfragt, Then `closingBalance` = Stand per 30.11.2025 (kumulativ, NICHT November-Bewegung). | must |
| 4 | Given Bexio-Connector mit lokal aggregiertem Saldo, When alle Journal-Eintraege im Importfenster liegen und kein Vortrag existiert, Then `closingBalance` einer Periode = Summe aller debits - Summe aller credits bis Periodenende fuer dieses Konto. | must |
| 5 | Given Connector wirft Exception in `getAccountBalances`, When der Sync laeuft, Then erscheint die Fehlermeldung in `summary["errors"]`, der Sync laeuft weiter und der Fallback befuellt die Tabelle aus den Journalzeilen. | must |
| 6 | Given Frage an AI-Agent "Wie hoch war der Saldo Konto 1020 per 31.12.2025?", When `queryData(entity="balances", mode="raw")` aufgerufen wird, Then enthaelt das Resultat den Datensatz mit `closingBalance=48507.41`. | must |
| 7 | Given Sync-Lauf, When er fertig ist, Then enthaelt das Log eine Zeile `Persisted N balances for <id> in Xs (source=buha\|local-fallback)`. | should |
## Testplan
| ID | AC | Art | Automatisiert | Repo-Pfad | Status |
|----|----|-----|--------------|-----------|--------|
| T1 | 1, 2, 3 | unit | ja | gateway/tests/unit/features/trustee/test_accountingConnectorRma_balances.py | 17/17 passed |
| T2 | 4 | unit | ja | gateway/tests/unit/features/trustee/test_accountingConnectorBexio_balances.py | 8/8 passed |
| T3 | 4 | unit | ja | gateway/tests/unit/features/trustee/test_accountingConnectorAbacus_balances.py | 6/6 passed |
| T4 | 1-3, 5 | integration | ja | gateway/tests/unit/features/trustee/test_accountingDataSync_balances.py (FakeDb) | 11/11 passed |
| T5 | 1, 2, 6 | manual | nein | PROD-Mandant `BuHa SoHa`, vorher/nachher Vergleich | pending (nach Deployment) |
## Links
- Bug-Report (Kunden-E-Mail vom 2026-04-25)
- RMA API Doc Saldo: <https://runmyaccountsag.github.io/runmyaccounts-rest-api/Resources/resources.html#general-ledger>
- Bexio Journal API: <https://docs.bexio.com/#tag/Accounting/operation/listJournal>
- Abacus REST API: <https://downloads.abacus.ch/fileadmin/ablage/abaconnect/htmlfiles/docs/restapi/abacus_rest_api.html>
## Abschluss
- [x] `wiki/b-reference/gateway/features/trustee.md` aktualisiert (Quelle der
Saldenliste).
- [x] `wiki/TOPICS.md` -- kein neuer Eintrag noetig (faellt unter Trustee).
- [x] Dieses Dokument in `wiki/c-work/4-done/` verschoben.

41
c-work/_CHANGELOG.md Normal file
View file

@ -0,0 +1,41 @@
<!-- status: canonical -->
<!-- lastReviewed: 2026-04-25 -->
# Changelog (c-work)
Eine Zeile pro Change, neueste oben. Begruendungen gehoeren ins zugehoerige
`c-work/<phase>/<feature>.md` oder die PR-Beschreibung.
Format: `- YYYY-MM-DD | <type> | <scope> | <Kurzbeschreibung> [(c-work: <relPfad>)] [(PR: #123)]`
type: `feat` `fix` `refactor` `docs` `test` `chore` `build` · scope: `gateway` `frontend-nyla` `private-llm` `teams-bot` `wiki` `infra` `*`
Skip: reine Refactors, Formatting, Lint, Dep-Bumps, Test-only, Wiki-Tippfehler.
## 2026-04-25
- 2026-04-25 | feat | * | Phase 4 FK: `frontend_fk_*` und FormGenerator-`fkSource`/Client-Cache entfernt; `fk_label_field` + `displayField` only; `_resolveRoleLabels`; `getRecordsetPaginated` + `getRecordsetPaginatedWithRBAC` + FK-Sort-Pfad mit `_enrichRowsWithFkLabels`; `attributeUtils` + betroffene Datamodels + Pages auf reines Backend-Enrichment
- 2026-04-25 | fix | gateway | Trustee Account Balances: echte Schlusssalden aus Buchhaltungssystem importieren (RMA via `/gl/saldo`; Bexio via Journal-Aggregation; Abacus via OData-Aggregation); korrigierte kumulative Fallback-Berechnung in `_persistBalances`; neues `AccountingPeriodBalance`-Modell + `getAccountBalances`-Methode in `BaseAccountingConnector`; Bug "Banksaldo per Stichtag falsch" (BuHa SoHa Konto 1020) geloest (c-work: c-work/4-done/2026-04-trustee-account-balances-import.md)
- 2026-04-25 | test | gateway | Unit-Tests fuer Trustee-Balance-Import: RMA-Connector (BuHa-SoHa-Szenario + ER-Reset), Bexio-Connector (kumulative Aggregation + Carry-Over), Abacus-Connector (OData-Aggregation), AccountingDataSync (Connector-Path + Local-Fallback)
- 2026-04-25 | feat | gateway | FK-Resolution Phase 2 (A1+A2): Neue zentrale `_enrichRowsWithFkLabels()` in `routeHelpers.py` — bulk-resolved FK-Labels als `{field}Label`-Spalten pro Row; `_resolveMandateLabels`/`_resolveInstanceLabels`/`_resolveUserLabels` liefern `None` statt ID bei fehlender Aufloesung; `routeWorkflowDashboard`, `routeAudit`, `routeBilling` (Transactions + Billing-Aggregation), `routeSubscription` auf zentrale Funktion migriert (`or mid[:8]` / `or uid[:8]` / `or iid`-Fallbacks entfernt)
- 2026-04-25 | feat | gateway | FK-Resolution Phase 2 (B2): `_enrichedFilterValues` in `routeWorkflowDashboard` liefert `{value, label}` Objekte fuer FK-Spalten (mandateId, featureInstanceId) — Frontend zeigt Labels im Filter-Dropdown ohne separate `fkSource`-Aufloesung; Leerwerte (`null`) fuer "(Leer)"-Filter inkludiert
- 2026-04-25 | fix | gateway+frontend | FK-Resolution Korrektur: `routeWorkflowDashboard` runs/workflows-Enrichment benennt `mandateIdLabel``mandateLabel` um (Frontend-Interface-Kompatibilitaet); `AutomationsDashboardPage` Spalten mandateId/featureInstanceId nutzen `displayField: 'mandateLabel'/'instanceLabel'`
- 2026-04-25 | feat | gateway | FK-Resolution Phase 2 (B1): `getDistinctColumnValues` + `getDistinctColumnValuesWithRBAC` + `_extractDistinctValues` + `_distinctColumnValues` liefern `null` als letzten Eintrag wenn NULL/Leer-Zeilen existieren — Frontend kann "(Leer)"-Filter anbieten
- 2026-04-25 | feat | frontend-nyla | FK-Resolution Phase 3 (C1+C2): `FormGeneratorTable.ColumnConfig.displayField` — neues Pattern: Cell rendert `row[displayField]` statt `row[key]`, CSV nutzt `displayField`; `fkSource`/`fkDisplayField` als `@deprecated` markiert (Legacy-Pfad funktioniert weiterhin)
- 2026-04-25 | feat | frontend-nyla | FK-Resolution Phase 3 (B3): `FilterValuesList` akzeptiert `string | null | {value, label}` Eintraege; `FilterValue`-Typ eingefuehrt; `_normalizeFilterValue` normalisiert alle 3 Formate; Backend-`null`-Eintraege werden als "(Leer)"-Option gerendert
- 2026-04-25 | fix | gateway | Fallback-Cleanup Phase 1 (D1+D2): Pagination-Parsing in `routeWorkflowDashboard` (runs/workflows) und `routeDataMandates` wirft 400 bei kaputtem JSON statt silent default; `runsByStatus`/Run-Enrichment in `/metrics` + `/workflows` propagieren DB-Fehler statt `logger.warning`+200; `delete_system_workflow` Callback-Trigger meldet Listener-Bugs (500 statt `except: pass`); `routeBilling._isAdminOfMandate`/`_isMemberOfMandate` und `routeSubscription._assertMandateAdmin` fail-loud (kein "DB-Down → 403"-Mask mehr); Stripe `Subscription.retrieve` im Checkout-Webhook re-raised statt silent skip
- 2026-04-25 | fix | gateway | Fallback-Cleanup Phase 1 (D2): `routeInvitations` Rollen-Zuweisung — `addRoleToFeatureAccess`/`addRoleToUserMandate` sind bereits idempotent, daher `try/except: pass # Role might already be assigned` entfernt → echte FK-/DB-Fehler beim Einladungs-Akzept werden jetzt sichtbar
- 2026-04-25 | fix | frontend-nyla | Fallback-Cleanup Phase 1 (D3+D4): `AutomationsDashboardPage._handleExecute` zeigt "Workflow gestartet" nur noch, wenn die 1s-Beobachtungs-Phase weder Erfolg noch Fehler beobachtet hat (kein Doppel-Toast "gestartet" + "fehlgeschlagen" mehr); `_loadMetrics` toast-t Backend-Fehler statt nur `console.error`; `Automation2FlowEditor.handleWorkflowRename` zeigt Fehler-Toast statt unsichtbarem `console.error`
- 2026-04-25 | feat | frontend-nyla | `FormGeneratorTable`: Leerwert-Filter `(Leer)` in allen Filter-Dropdowns — filtert auf `IS NULL OR = ''` (Backend unterstützt bereits `null` in Pagination-Filtern); Filter-Icon/Clear-Button erkennen `null`-Filter korrekt via `key in filters`
- 2026-04-25 | fix | frontend-nyla | NodeConfigPanel/RequiredAttributePicker/FeatureInstancePicker: Texte (Type-Badges, Bound-Refs, Vorschlag-Labels, Beschreibungen) verlassen den 280px-Panel-Frame nicht mehr — Header-Layout `label flex:1 1 100 %` lässt Badge umbrechen; `box-sizing: border-box`, `overflow-x: hidden`, `overflow-wrap: anywhere` als Safety-Net auf `.nodeConfigPanel`; Bound-Chip/Vorschlag-Button mit `whitespace: normal` + `word-break`
- 2026-04-25 | fix | frontend-nyla | KeepAlive-Wrapper (`GraphicalEditor`, `Workspace`, `Commcoach`): Persistenz strikt pro `(mandateId, instanceId)``key={mandate:instance}` an die gehaltene Page; Wechsel der Mandanten-/Instanz-Tupel unmountet den alten Editor (kein Cross-Tenant-Save mehr, "not found"-Bug behoben); Unit-Test `GraphicalEditorKeepAlive.test.tsx`
- 2026-04-25 | fix | frontend-nyla | `DataPicker`: per `createPortal` nach `document.body` (entkoppelt von `.nodeConfigPanel button`-Primary-Override); neues List-Row-Layout/Theme (`dataPickerNodeHeader` neutral), Header-Badge/Filter/Close-Styles, höheres z-index
- 2026-04-25 | fix | frontend-nyla | Flow-Editor `CanvasHeader`: Zwei-Spalten-Layout (Kontext: fester Workflow-Dropdown + Titel mit Ellipsis | Aktionspanel); Run-Button `min-width`; Version-Zeile getrennt; `retryButton`-Margin im Toolbar-Panel neutralisiert
- 2026-04-25 | fix | gateway | Trustee-Template `trustee-receipt-import`: `documentList` als DataRef `extract→process→sync` (Pick-not-Push), nicht leere Listen; Unit-Test `test_trustee_template_workflows.py`
- 2026-04-25 | feat | gateway | Trustee + Redmine Nodes auf typisierten `FeatureInstanceRef[<code>]`-Param + `frontendType: featureInstance` migriert (c-work: c-work/4-done/2026-04-feature-instance-ref-adapter-migration.md)
- 2026-04-25 | feat | gateway | Neuer Endpoint `GET /api/workflows/{instanceId}/options/feature.instance?featureCode=…` fuer Mandanten-gefilterte FeatureInstance-Auswahl (c-work: c-work/4-done/2026-04-feature-instance-ref-adapter-migration.md)
- 2026-04-25 | feat | frontend-nyla | `FeatureInstancePicker` (0/1/N) als Renderer fuer `frontendType: featureInstance`; Sysadmin-Toggle "Schema-Details" im CanvasHeader (c-work: c-work/4-done/2026-04-feature-instance-ref-adapter-migration.md)
- 2026-04-25 | fix | frontend-nyla | NodeConfigPanel-Banner zeigt `param.name` statt der ausschweifenden Description (Tooltip enthaelt vollen Text); hidden-Pflicht-Params werden zentral in `findRequiredErrors` gefiltert (kein Phantom-Pflichtfeld mehr) (c-work: c-work/4-done/2026-04-feature-instance-ref-adapter-migration.md)
- 2026-04-25 | fix | frontend-nyla | DataPicker-Modal auf CSS-Variablen umgestellt; Hover-Safety-Net `dataPickerLeaf:hover *` haelt Type-Hints auf blauem Hintergrund lesbar (c-work: c-work/4-done/2026-04-feature-instance-ref-adapter-migration.md)
- 2026-04-25 | docs | wiki | Audit `2026-04-node-typization-audit.md` archiviert; Folge-Track-Doc `2026-04-feature-instance-ref-adapter-migration.md` direkt in `4-done/` als erledigt
- 2026-04-25 | docs | wiki | Changelog-Konvention im `_CHANGELOG.md` eingefuehrt; in `README.md` + `doc-sync.mdc` referenziert

View file

@ -1,5 +1,5 @@
<!-- status: canonical -->
<!-- lastReviewed: 2026-04-06 -->
<!-- lastReviewed: 2026-04-25 -->
# Cursor-Regel: Doc-Sync
@ -29,4 +29,5 @@ if (-not (Test-Path $dst)) {
- Erinnert bei Änderungen an API, Domain-Logik, Security, RBAC, Navigation, Features, Billing
- Während Arbeit: `c-work/<phase>/<feature>.md` pflegen
- Bei Abschluss: betroffene `b-reference/` Seite + `TOPICS.md` aktualisieren
- Immer: 1 Zeile in [`c-work/_CHANGELOG.md`](../c-work/_CHANGELOG.md) (Format dort)
- Kein Doku-Zwang bei reinen Refactors, Formatting oder Test-only Changes

View file

@ -1,16 +1,18 @@
<!-- status: reference -->
<!-- status: superseded -->
<!-- lastUpdated: 2026-04-24 -->
<!-- lastReviewed: 2026-04-24 -->
<!-- lastReviewed: 2026-04-25 -->
<!-- archivedOn: 2026-04-25 -->
<!-- supersededBy: b-reference/gateway/workflow.md (Typed Action Architecture) -->
<!-- related: c-work/4-done/2026-04-typed-action-architecture.md, c-work/4-done/2026-04-typed-action-followups.md -->
# Node-Typisierungs-Audit (Stand 2026-04-24)
Faktenbasis fuer den abgeschlossenen Plan
[`2026-04-typed-action-architecture.md`](../4-done/2026-04-typed-action-architecture.md)
sowie den Folge-Plan
[`2026-04-typed-action-followups.md`](../4-done/2026-04-typed-action-followups.md).
Beide Plaene sind erledigt; das Audit bleibt als historische Referenz unter
`1-plan/`, weil es weiterhin die Faktenbasis fuer Drift-Diskussionen ist.
> **ARCHIVIERT 2026-04-25.** Die 4 Defekt-Muster sind durch die
> [Typed Action Architecture](../../b-reference/gateway/workflow.md)
> und ihre [Folge-Schritte](../c-work/2026-04-typed-action-followups.md)
> strukturell beseitigt. Bug-Restbestand (Trustee/Redmine-Adapter noch nicht
> migriert) wurde in `c-work/4-done/2026-04-feature-instance-ref-adapter-migration.md`
> erledigt. Diese Seite bleibt nur als historische Faktenbasis erhalten.
Quelle: `gateway/modules/features/graphicalEditor/nodeDefinitions/*.py`
manuell ausgelesen aus 12 Node-Definition-Dateien (53 Nodes total).

2556
z-archive/changelog.txt Normal file

File diff suppressed because it is too large Load diff