# UDB Toggle Spec Recovery ## Kontext Nach dem Generic Tree Refactor (2026-05-18) waren im Code sechs Aggregations-Routinen (`_aggregatePersonalRoot`, `_aggregateConnection`, `_aggregateMandateGroup`, `_resolveAttrsForKey`, `getAttributesForKeys`), ein paralleler Endpoint `POST /tree/attributes` und ein Bug bei virtuellen Coordinates (kein aggregate fuer Records ohne DB-Eintrag) entstanden. Das Frontend nutzte `refreshAttributes` als optionalen Pfad und `refreshAfterAction` als Opt-in-Prop, obwohl die Spec nur einen Pipeline-Pfad vorsieht. ## Ziel Wiederherstellung der dokumentierten Spec (2026-05-18 "Generic Tree Refactor"): **Eine** Pipeline, **ein** Resolver, **ein** Mixed-Symbol, **drei** Flags generisch durch denselben Code-Pfad. Keine optimistic updates, keine Fallbacks, keine doppelte Logik. ## Durchgefuehrte Aenderungen ### S1 - Backend: virtuelle Coordinates auf aggregate-Pfad `_inheritFlags.py`: `resolveEffectiveForPath` und `resolveEffectiveForFds` rufen im else-Zweig (virtual record, kein DB-Match) nun `getEffectiveFlag(virtualRec, flag, allDs, mode=mode)` bzw. `getEffectiveFlagFds(...)` statt `_resolveWalkValue` auf. Damit koennen virtuelle Coordinates (z.B. Connection ohne eigenen Root-Record) korrekt `'mixed'` zurueckgeben, wenn ihre Descendants divergieren. ### S2 - Backend: sechs Aggregatoren entfernt `_buildTree.py`: Geloescht: `_aggregatePersonalRoot`, `_aggregateConnection`, `_aggregateMandateGroup`, `_resolveAttrsForKey`, `getAttributesForKeys`. Diese waren ausschliesslich fuer den parallelen `tree/attributes`-Endpoint noetig. Synthetic Container (`personalRoot`, `mgrp`) haben laut Spec keine Flags (UI blendet sie aus); data-bearing Nodes nutzen bereits `resolveEffectiveForPath`/`resolveEffectiveForFds` via den tree builder. ### S3 - Backend: Endpoint tree/attributes entfernt `routeFeatureWorkspace.py`: Route `POST /{instanceId}/tree/attributes` und Model `_TreeAttributesRequest` ersatzlos geloescht. ### S4 - Frontend: refreshAttributes-Pfad entfernt - `UdbSourcesProvider.tsx`: `refreshAttributes`-Methode entfernt. - `FolderFileProvider.tsx`: `refreshAttributes`-Methode entfernt. - `FormGeneratorTree.tsx`: `_refreshVisibleAttributes` nutzt nur noch den Refetch-All-Expanded-Pfad. `_runAction` ruft immer `_refreshVisibleAttributes` ohne Bedingung. `refreshAfterAction`-Prop entfernt. - `types.ts`: `refreshAttributes` aus `TreeNodeProvider`, `refreshAfterAction` aus `FormGeneratorTreeProps` entfernt. - `SourcesTab.tsx`, `FilesTab.tsx`: `refreshAfterAction`-Prop-Nutzung entfernt. ### S5 - Klick-Semantik dokumentiert `wiki/b-reference/platform/neutralization.md`: Klick auf mixed-Symbol setzt explizit `false` (alle Flags). Begruendung: Toggle behaelt zwei klare End-Zustaende; Reset auf `null`/inherit durch Parent-Toggle. ### S6 - Tests 8 neue Tests in `test_inheritFlags.py::TestVirtualCoordAggregate`: - virtual folder mixed neutralize/scope/rag - virtual folder uniform returns concrete - virtual FDS workspace mixed/uniform - virtual connection root mixed via diverging services Frontend-Test `refreshAfterAction` angepasst: zweiter Test (does NOT refetch when false) entfernt, da Verhalten nun immer refetch ist. Resultat: `test_inheritFlags.py` 79/79 gruen, `test_buildTree.py` 19/19 gruen. ## Validierung (Smoke-Tests vor Merge) 1. Folder mit zwei Subfolders, einer toggeln -> Parent zeigt mixed, Root zeigt mixed, Personal Root zeigt mixed. 2. Parent toggeln (war mixed) -> Parent + alle Descendants zeigen den Parent-Wert. 3. Klick auf mixed-Symbol -> setzt explizit `false`, Spinner bleibt bis Refetch durch ist. 4. Toggle in collapsed Subtree (verstecktem Knoten) -> nach expand zeigt Subtree die neuen Werte. 5. Mandate mit zwei Workspaces, einer toggeln -> mgrp zeigt mixed.