konzept vertraulich owner: matus
Demo-Daten-Tooling bündeln — Vergleich mit eimr/evenews/evepop/DOT
Demo-Daten-Tooling bündeln — Vergleich mit eimr/evenews/evepop/DOT
Status: umgesetzt in drei Iterationen (alle 2026-08-15) · Adressat: Product Owner · Art: Iterationen 1–2 UI/Navigation; Iteration 3 zusätzlich Backend (zwei neue Demo-Bundles) — keine neue Fachzahl, keine berührte Leitplanke
Lesehinweis: Die Abschnitte bis „Warum Test-/Demo-Elemente überhaupt auf Fachseiten landeten" beschreiben die erste Iteration (Demo-Tooling raus aus den Fachseiten, rein in eine eigene Sektion). Sie ließ Laden und Löschen auf einer Seite. Der Abschnitt „Zweite Iteration" korrigiert das und enthält die tiefere, im Code nachgeprüfte Vergleichsanalyse (inklusive der präzisierten DOT-Antwort). Die „Dritte Iteration" macht aus dem einen Referenzfall drei und benennt dabei eine gefundene, bewusst nicht behobene Lücke im Auswertungslauf. Bei Widersprüchen gilt der spätere Abschnitt — insbesondere ist die in Iteration 2 begründete Wortwahl „Referenzfall laden" statt „Demo-Vorlagen" seit Iteration 3 überholt.
Anlass war eine Nutzerbeobachtung im Screenshot-Vergleich: das Demo-Daten-Tooling und der Testfallkatalog sahen in tuxametrics „nicht annähernd so gut aus" wie in den Schwesterprodukten. Auftrag war zunächst nur Analyse, dann („SETZE ES UM") die Umsetzung der Schritte 1–3 unten. Dieses Dokument hält fest, was die Schwesterprodukte tatsächlich haben, was tuxametrics vorher hatte, was übernommen wurde — und was ausdrücklich nicht.
Dieses Thema berührt keine der fünf Leitplanken aus CLAUDE.md. GM-7 ist hier irrelevant:
Demodaten laden und löschen ist keine klinische Entscheidung und kein Schritt der Freigabekette.
txm.demo.cleanup ist zwar NUR_MENSCHEN
(tuxametrics-laborauswertung-service/src/main/java/io/dl/tuxametrics/laborauswertung/service/capability/CapabilityRegistrar.java,
Z. 151–155) — aber laut eigener Begründung dort nicht aus GM-7-Gründen, sondern wegen der
Tragweite eines mandantenweiten Datenverlusts.
Zwei korrigierte Prämissen
Beide Korrekturen betreffen die Ausgangsannahme, nicht die Sache. Sie stehen hier, weil sonst das falsche Repo als Vorbild herangezogen wird.
| Annahme | Befund |
|---|---|
| „DOT hat eine Demo-Sektion" | Nein. C:\dev\dot\dot\dot-platform-ui hat kein domains/demo, keinen Sidebar-Eintrag „Demo" und keinen Testfallkatalog im Frontend. Was es gibt, ist eine Datenbereinigung unter Administration: domains/administration/sidebar.ts Z. 21 (administration/data-cleanup) und domains/administration/pages/DataCleanupPage.tsx — PageHeader, Type-to-confirm, zwei capability-gegatete Aktionen. Der Rest des DOT-Demo-Tooling ist skript-/dokumentationsbasiert (DOT/DEMO_DATA.md, scripts/reset-odc-demo.mjs u. a., per node-CLI). DOT ist also kein Vorbild für Bündelung, aber ein Beleg dafür, dass eine eigene Cleanup-Seite produktübergreifend Standard ist. |
| „Testmanagement wie bei evepop" | evepop hat die dünnste Lösung der drei. evepop-platform-ui/src/domains/testing/ enthält nur api/, hooks/, model/, index.ts — keine Seiten; es wird inline als Widget in domains/process-hub/pages/ProcessDefinitionDetailPage.tsx benutzt. Der frühere Cleanup-Eintrag ist laut Kommentar in domains/administration/sidebar.ts Z. 7–9 am 2026-08-13 nach eimr-ui gewandert. evepop steht damit für die Zwirn-Testmanagement-Basis, nicht für ein Frontend-Vorbild. Das deckt sich mit der bereits im Repo stehenden Selbstkorrektur in testmanagement-integration.md („Korrektur 2026-08-14"). |
Das echte Vorbild ist eimr, sekundär evenews.
Was eimr und evenews tatsächlich haben
eimr (eimr-ui/src/domains/demo) |
evenews (evenews-ui/src/domains/demo) |
|
|---|---|---|
| Sidebar-Sektion | „Demo", Icon FlaskConical, basePath: demo-tools (sidebar.ts) |
„Demo", Icon Wand2, basePath: blueprints (sidebar.ts) |
| Section-weites Capability-Gate | nein — je Item eines | nein — je Item eines |
| Items | Testgruppen · Demo-Vorlagen (Mocks) · Testdaten zurücksetzen | Demo-Vorlagen (Blueprints) · Mocked Services · Cleanup |
| URL-Präfix | demo-tools/ (nicht demo/ — Test-Tenant heißt „demo", ADR-0053) |
keins — Items liegen direkt auf Tenant-Ebene (ADR-0055, routes.tsx Kopfkommentar). Die Sektion ist ein reines UI-Gruppierungskonzept. |
| Testkatalog-Tiefe | 6 Routen, fünfstufig bis …/test-cases/:key/processes (routes.tsx) |
keiner |
| Cleanup | CleanupPage.tsx: drei Services sequentiell, Schrittliste mit pending/running/done/error, Type-to-confirm auf Tenant-Key |
CleanupPage.tsx: ein Service, deshalb ausdrücklich keine Schrittliste (Kopfkommentar Z. 12–15), sonst identischer Aufbau |
| Mocks | Tabelle + „Alle Mocks starten" (Bulk-Run mit Polling, MocksListPage.tsx) |
nach Typ gruppiertes Grid, Einzel-/Gruppen-/Alle-Trigger, sechs Typen über eine parametrisierte Seite (BlueprintTypeListPage.tsx, ADR-0054) |
| i18n | src/i18n/locales/demo/{de,en}.json, 29 Zeilen (nur Cleanup — der Rest ist hartcodiertes Deutsch) |
dieselben Dateien, 166 Zeilen (Cleanup + Blueprints vollständig) |
| Kein-Zugriff-Verhalten | TestGroupsPage.tsx/CleanupPage.tsx rendern statt der Seite einen „Keine Berechtigung"-Block |
dito |
Gemeinsamer Nenner beider, und das ist der eigentliche Kern der Nutzerbeobachtung:
- eine Sidebar-Sektion, die Testkatalog + Demo-Vorlagen + Cleanup bündelt,
- Cleanup als eigene Seite mit eigener Route, nicht als Beiwerk einer Fachseite,
- jede Seite mit
PageHeader(Breadcrumbs, Icon, Titel, Untertitel, Aktionsleiste rechts).
Ist-Zustand tuxametrics
| Punkt | Fundstelle | Bewertung |
|---|---|---|
| Keine „Demo"-Sektion | tuxametrics-ui/src/nav/navConfig.ts |
„Testfälle" ist eine eigene Sektion mit einem Item („Übersicht", Z. 100–104) in der unteren Gruppe „Technische Daten". Eine Sektion mit einem Kind ist die teuerste Form, einen einzelnen Link zu zeigen. |
Kein requiredCapability in der Nav |
navConfig.ts Z. 24–29 |
Bewusste Produktentscheidung, ausformuliert im Datei-Javadoc: eine Sidebar, die Punkte je nach Rechten verschwinden lässt, verbirgt, dass es den Bereich gibt. Seit ADR-0007 existiert /me/capabilities — die Auslassung ist seitdem Entscheidung, nicht Lücke. Jede Empfehlung hier respektiert das. |
| Demodaten als Inline-Panel | src/shell/DemoDatenPanel.tsx, eingebunden in routes/PatientUebersichtRoute.tsx und routes/AuswertungUebersichtRoute.tsx |
Keine eigene Route, keine Breadcrumbs, keine adressierbare Seite. Die unwiderrufliche Löschaktion sitzt damit auf zwei fachlichen Alltagsseiten. |
| Cleanup-Dialog | src/shell/DemoDatenLoeschenDialog.tsx |
Type-to-confirm ist vorhanden und gut. Ein einziger Backend-Call (auswertungApi.loescheDemoDaten → DemoCleanupResource). Das Ergebnis trägt zehn Zähler (DemoCleanupErgebnis), angezeigt werden zwei (Patienten, Auswertungen, Z. 106–107). |
| Nur ein Fachservice betroffen | DemoCleanupResource |
Anders als eimrs drei Services (Finance/Process/TestRuns) — architektonisch bedingt, kein Rückstand. evenews steht vor genau derselben Lage und hat daraus dieselbe Konsequenz gezogen. |
| Genau 1 von 63 Mock-Szenarien | src/shell/TestfallAusfuehren.tsx Z. 9–19 (MOCK_SZENARIEN) |
Dokumentiert und gewollt in testmanagement-integration.md („Was danach noch offen ist"). Prinzip im Javadoc: keine erfundene Vollständigkeit. |
| Testfälle-Slice | src/domains/testfaelle/pages/{TestGruppenUebersichtPage,TestGruppeDetailPage,TestfallDetailPage}.tsx, components/{GoldPathDiagramm,TestCaseTable,TestfallStatusBadge}.tsx |
Card-Grid + Zähler + GoldPathDiagramm sind seit Commit 07bbc25 da („nach eimr-Vorbild"). Der Katalogteil ist nicht weit zurück; was fehlt, ist die Bündelung und die Seitenchrome. |
Kein PageHeader |
Grep in tuxametrics-ui/src: 0 Treffer |
Siehe nächster Abschnitt — das ist kein fehlender Baustein. |
useCapabilities |
src/domains/autoimprove/features/report/components/AutoImproveReportModal.tsx Z. 6, aus @zwirn/web |
Bereits einmal im Produkt in Gebrauch. Der Hook ist also weder neu noch ungetestet. |
PageHeader und useCapabilities sind keine neue Abhängigkeit
Beide liegen in @zwirn/web, das dieses Produkt bereits als file:-Dependency zieht:
tuxametrics-ui/node_modules/@zwirn/web/src/index.ts Z. 10 (useCapabilities), Z. 51–52
(PageHeader, Crumb). eimrs src/components/layout/PageHeader.tsx ist ein zweizeiliger
Re-Export desselben Pakets, keine Eigenentwicklung. Für tuxametrics wäre es ein Import, kein Nachbau.
Zwei Dinge sind dabei sauber auseinanderzuhalten:
- Breadcrumbs/PageHeader haben mit Capabilities nichts zu tun. Sie zu übernehmen berührt die
Entscheidung aus
navConfig.tsnicht im Geringsten. - Capability-Gating pro Aktion widerspricht ihr ebenfalls nicht —
navConfig.tsZ. 26–27 sagt wörtlich, „die Seiten dahinter gaten ihre Aktionen selbst". Heute tut die Löschaktion das nicht: fehlt der Grant, tippt der Nutzer erst den Mandantenschlüssel ab und bekommt dann einen 403 überfachlicherFehler. Ein Button, der sichtbar bleibt, aber deaktiviert ist und den fehlenden Schlüssel benennt, ist die transparenzkonforme Variante. Was nicht übernommen werden darf, ist eimrs/evenews' „Keine Berechtigung"-Block anstelle der ganzen Seite — das ist genau das Verstecken, dasnavConfig.tsablehnt.
Konkrete Falle bei PageHeader: die Komponente bringt eigenes px-6 pt-5 mit und setzt voraus,
dass sie oberstes Element in einem ungepolsterten main ist. shell/AppLayout.tsx erfüllt das
(<main className="flex-1 min-w-0 overflow-auto">), aber jede heutige Seite bringt ihr eigenes p-4
mit (z. B. TestGruppenUebersichtPage.tsx Z. 65). Wer PageHeader einsetzt, muss das äußere Padding
der Seite entfernen, sonst entsteht doppelter Rand.
Empfehlung: was übernehmen, was nicht
Übernehmen
| Vorschlag | Begründung |
|---|---|
| Eine Sidebar-Sektion „Demo", die „Demodaten" und „Testfälle" bündelt; die Einzel-Sektion „Testfälle" entfällt | Genau der Kern der Nutzerbeobachtung. Beseitigt zugleich die Ein-Kind-Sektion. Bleibt in der Gruppe „Technische Daten" — Demo-Tooling ist kein Gold-Path-Schritt. |
| Cleanup + Referenzfall-Laden als eigene Route/Seite | Der Punkt, an dem eimr/evenews/DOT alle drei übereinstimmen. Eine unwiderrufliche mandantenweite Löschung gehört nicht auf die Patientenliste. |
| Alle zehn Zähler im Löschergebnis zeigen | DemoCleanupErgebnis liefert sie bereits; heute werden zwei angezeigt. Auf einer eigenen Seite ist Platz für eine kleine Ergebnistabelle. Kein Backend-Eingriff. Damit ist die Ergebnisdarstellung sogar detaillierter als eimrs. |
PageHeader auf den Seiten der neuen Sektion (Demodaten + die drei Testfälle-Seiten) |
Der sichtbarste Teil des optischen Abstands. Import statt Nachbau. |
Kein URL-Präfix demo/ — die Sektion bleibt reines UI-Gruppierungskonzept |
Genau evenews' Schluss (ADR-0055). Für tuxametrics kommt ein zweiter Grund dazu: testfaelle liegt bereits unter :tenantKey/testfaelle, und die Route umzuhängen bräche bestehende Links ohne Gegenwert. |
Nicht übernehmen
| Vorschlag | Warum nicht |
|---|---|
| Mocks-/Blueprint-Übersicht als Grid | Es gibt ein ausgearbeitetes Szenario (MOCK_SZENARIEN, TC-AUS-013). Ein Grid oder eine Vorlagen-Liste über einen Eintrag suggeriert eine Verwaltungsfläche, die nichts zu verwalten hat — genau die „erfundene Vollständigkeit", die TestfallAusfuehren.tsx Z. 13–14 ausdrücklich ablehnt. Auch eine editierbare Mock-Verwaltung wie evenews scheidet aus: dahinter steht dort ein Service mit CRUD; tuxametrics hat POST /demo/referenzfall, sonst nichts. |
| Mehrstufige Cleanup-Schrittliste (eimr) | Ein Backend-Call. Eine Fortschrittsliste mit einem Schritt ist Theater. evenews hat für dieselbe Lage dieselbe Entscheidung getroffen und sie im Kopfkommentar seiner CleanupPage.tsx begründet — inklusive des Rückwegs, falls ein zweiter Service dazukommt. |
Section-weites requiredCapability |
Widerspricht navConfig.ts Z. 24–29 frontal. |
| „Keine Berechtigung"-Seite statt Inhalt | Dito — Verstecken statt Erklären. |
i18n-Namespace demo/{de,en}.json |
tuxametrics ist einsprachig Deutsch, NavItem hat kein labelKey (navConfig.ts Z. 23). Ein Namespace für eine Sprache wäre Aufwand ohne Nutzen. |
Katalog-Admin-UI (Gruppen/Fälle anlegen, status pflegen) |
Steht bereits als offener Punkt in testmanagement-integration.md und ist ein eigenes Thema, nicht Teil dieser Bündelung. |
| Neue Capabilities | Keine nötig. txm.demo.load und txm.demo.cleanup existieren, sind im Katalog registriert (laborauswertung-service/.../capability/CapabilityRegistrar.java Z. 148–155) und im Demo-Grantsatz enthalten (tuxametrics-platform-service/.../boot/CapabilityRegistrar.java Z. 77–78, Schalter TXM_DEMO_GRANTS). Die Katalog-Lese-Rechte des Testmanagement-Service ebenso. |
Umsetzungsschritte
Sequenziert, jeder Schritt für sich lauffähig und einzeln abbrechbar. Nach jedem Schritt:
cd tuxametrics-ui && npm run typecheck. Kein Backend-Eingriff in keinem Schritt.
Schritt 1 — Nav bündeln (kleinster sichtbarer Gewinn, keine neue Route)
tuxametrics-ui/src/nav/navConfig.ts: neue Sektionid: 'demo', Label „Demo", IconWand2(nichtFlaskConical— das ist in diesem Produkt schon für „Auswertungen" vergeben, Z. 72). Items zunächst nur{ label: 'Testfälle', path: 'testfaelle', end: true }. Die bisherige Sektiontestfaelleentfällt.- Reihenfolge in der Gruppe „Technische Daten": Protokoll → Demo → Autoimprove. Achtung:
shell/Sidebar.tsxbestimmt den Gruppenanfang überfindIndex(s => s.groupLabel)und liest das Gruppenlabel austechnicalSections[0]— die Sektionauditmuss erste der Gruppe bleiben und dasgroupLabelbehalten.
Schritt 2 — Demodaten-Seite
- Neu:
tuxametrics-ui/src/routes/DemodatenRoute.tsx—ReferenzfallLadenButton+ Löschbereich + Ergebnistabelle über alle zehn Zähler. - Neu (aus dem Bestehenden herausgelöst):
src/shell/DemoDatenLoeschenPanel.tsx— der Inhalt vonDemoDatenLoeschenDialog.tsxohne den eingeklappten Auslöse-Button; auf einer eigenen Seite ist das Aufklappen sinnlos.DemoDatenLoeschenDialog.tsxkann danach entfallen oder zum dünnen Wrapper werden — je nachdem, wie Schritt 3 ausgeht. src/App.tsx: Route:tenantKey/demodateninnerhalbSystemsteckbriefFrame, analog Z. 139–142.src/nav/navConfig.ts: Item „Demodaten" (demodaten, IconDatabase) vor „Testfälle".
Schritt 3 — Fachseiten entlasten
src/shell/DemoDatenPanel.tsx,src/routes/PatientUebersichtRoute.tsx,src/routes/AuswertungUebersichtRoute.tsx.- Empfohlene Variante: auf den beiden Fachseiten bleibt der
ReferenzfallLadenButtonplus ein Textlink „Demodaten verwalten" auf die neue Seite; der Löschteil verschwindet dort. Begründung: eine leere Patientenliste ohne sichtbaren Weg zu Daten ist ein schlechterer Erstkontakt als ein Button zu viel — die unwiderrufliche Hälfte aber gehört nicht dorthin. - Gegenrede, die zu entscheiden ist: das Javadoc von
DemoDatenPanel.tsxZ. 8–11 begründet die Paarung „was der eine anlegt, räumt der andere weg" ausdrücklich. Die Paarung bleibt auf der neuen Seite erhalten; auf den Fachseiten wird sie aufgelöst. Wer das anders sieht, entfernt das Panel dort ersatzlos (Variante B) — dann ist die Demodaten-Seite der einzige Einstieg.
Schritt 4 — PageHeader auf den vier Seiten der Sektion
src/routes/DemodatenRoute.tsx,src/domains/testfaelle/pages/TestGruppenUebersichtPage.tsx,TestGruppeDetailPage.tsx,TestfallDetailPage.tsx.- Import aus
@zwirn/web, kein lokaler Re-Export-Shim wie in eimr (ein Alias über zwei Zeilen bringt hier nichts). - Äußeres
p-4/p-6der jeweiligen Seite entfernen, sonst doppelter Rand (siehe oben). - Grenze dieses Schritts, ehrlich benannt: danach haben vier Seiten Breadcrumbs und der Rest des Produkts (Patienten, Auswertungen, Therapieplan, Bericht, Systemsteckbrief) nicht. Das ist eine sichtbare Naht. Sie ist vertretbar, weil sie einer zusammenhängenden Nav-Sektion folgt und nicht seitenweise gestreut ist — aber ein produktweiter Rollout ist ein eigenes, größeres Thema und gehört nicht in diese Session.
- Die
domains/*-Slices kennen lautREADME §Konventionenkeinen Router.PageHeaderrendert<Link>-Breadcrumbs. Sauberer Ausweg: den Header in den Route-Adaptern (routes/Testfaelle*Route.tsx) rendern und die Slice-Seiten unverändert lassen. Das hält die Konvention und ist zugleich weniger Code als Props durchzureichen.
Schritt 5 — optional: Löschaktion capability-bewusst
useCapabilities(tenantKey)aus@zwirn/web(Muster:AutoImproveReportModal.tsx).- Button sichtbar lassen, bei fehlendem
txm.demo.cleanupdeaktivieren und den fehlenden Schlüssel im Klartext danebenschreiben. Nicht die Seite ersetzen. - Wenn dieser Schritt kommt, gehört die Begründung als Kommentar an die Aktion und ein Hinweis in
das bestehende Javadoc von
navConfig.tsZ. 24–29 — sonst liest der nächste Leser einen Widerspruch, wo eine bewusste Abgrenzung steht.
Schritt 6 — Dokumentation
CHANGELOG.md,agentic-engineering/agent-log/<datum>.md, Indexzeile inagentic-engineering/BACKLOG.md, Querverweis austestmanagement-integration.mdhierher.
Braucht das ein ADR?
Vorschlag: nein. eimr und evenews haben für dasselbe Thema drei ADRs geschrieben (0053/0054/0055),
aber deren Inhalt war überwiegend das Auflösen einer URL-Namenskollision mit ihrem Test-Tenant
„demo" — ein Problem, das tuxametrics nicht hat (Mandanten heißen praxis01/praxis02,
navConfig.ts Z. 148–151) und das die Empfehlung oben ohnehin umgeht, indem sie keine Routen
umhängt. Keine der fünf Leitplanken ist berührt, kein Enum, kein Datenmodell, keine Fachzahl.
Dieses Backlog-Dokument ist der Nachweis. Ausnahme: sollte Schritt 5 zu einem produktweiten
Capability-Gating ausgebaut werden, wäre das eine Revision der Entscheidung in navConfig.ts und
bräuchte dann ein ADR.
Umgesetzt am 2026-08-15
Schritte 1–3 aus dem Plan oben, in einem Zug statt einzeln geprüft (Nutzerauftrag „SETZE ES UM"):
nav/navConfig.ts: Sektiondemo(IconWand2) ersetzt die Ein-Kind-Sektiontestfaelle. Items: „Demodaten" (demodaten, IconDatabase) und „Testfälle" (testfaelle, unverändert).- Neu:
routes/DemodatenRoute.tsx(Route:tenantKey/demodateninApp.tsx),shell/ DemoDatenLoeschenPanel.tsx(ausDemoDatenLoeschenDialog.tsxherausgelöst, ohne Ein-/Ausklapp- Button, jetzt mit allen zehn Zählern ausDemoCleanupErgebnisstatt zwei). - Entfernt:
shell/DemoDatenPanel.tsx,shell/DemoDatenLoeschenDialog.tsx. Beide Aufrufstellen inroutes/PatientUebersichtRoute.tsx/routes/AuswertungUebersichtRoute.tsxentfernt — ohne Ersatzlink (Variante B aus Schritt 3, nicht die dort vorgeschlagene Variante A): der Nutzer wollte explizit keine Demo-Daten-Aktion mehr auf den fachlichen Seiten sehen, auch keinen Textlink.PageHeader-Rollout (Schritt 4) und capability-bewusstes Deaktivieren (Schritt 5) sind nicht Teil dieser Umsetzung — beide bleiben offen, siehe unten. - BPMN-Aufräumen (separater, aber verwandter Auftrag desselben Tages): alle
(FACH-NNN...)-Suffixe aus den Element-Namen intuxametrics-auswertung.bpmn20.xmlentfernt und als<bpmn:documentation>abgelegt — vonBpmnViewer(@zwirn/bpmn,parseBpmnXml.ts/ElementDetailContent.tsx) bereits ungeändert im Klick-Detail-Popover angezeigt, kein Code-Eingriff nötig.GM-7.2anTask_ovrblieb bewusst im sichtbaren Namen (kein bloßer Fach-Verweis, sondern ein benannter Leitplanken-Bezug, siehe CLAUDE.md Leitplanke 2). Der „Happy Path"-Vergleich des Nutzers bezog sich, wie sich zeigte, auf ein bei eimr anderes, unabhängiges Feature (HappyPathStepper, fachlicher Fortschritts-Stepper auf Rechnungs-/Fallakten-Seiten) —@zwirn/bpmnenthält dieses Konzept laut eigenemindex.ts-Kommentar explizit nicht; es betrifft das BPMN-Diagramm selbst nicht und wurde deshalb nicht übernommen.
Warum Test-/Demo-Elemente ueberhaupt auf Fachseiten landeten — und warum das falsch ist
Nutzerauftrag: eine Begründung, warum es so weit kam, nicht nur die Korrektur selbst.
Wie es entstand — vier Ursachen, keine davon böswillig:
- Reihenfolge des Bootstrappings.
ReferenzfallLadenButton(und später der Lösch-Dialog) lösten ein akutes lokales Problem: eine leere Datenbank auf genau der Seite, die das am sichtbarsten zeigte (Patienten-/Auswertungsliste). Der Knopf landete dort, wo der Schmerzpunkt war — nicht dort, wo er strukturell hingehört. - Es gab noch keine passende Nav-Heimat. Bis 2026-08-13 hatte tuxametrics-ui IconRail + Untermenü,
keine feste „Werkzeug"-Sektion. Als die einheitliche Sidebar kam (Muster aus eimr/evenews,
navConfig.tsKommentar), zog nur der Testfallkatalog in einen eigenen Menüpunkt um — das Lösch-/Lade-Paar blieb aus Trägheit, wo es immer war. - Die Paarungs-Begründung verdeckte die Platzierungsfrage. Das alte
DemoDatenPanel.tsxhatte ein berechtigtes Argument: Laden und Löschen gehören zusammen. Das ist wahr — beantwortet aber nicht, ob die Seite, auf der beide zusammen saßen, die richtige war. Die Paarung wurde lokal gelöst (eine Komponente für beide Aktionen), ohne die Platzierung separat zu prüfen. - Zwei Knöpfe fühlten sich zu klein für eine eigene Seite an. Dieses Repo vermeidet erfundene
Struktur (
CLAUDE.md-Grundhaltung überall). Eine eigene Route für „zwei Buttons" wirkt wie Überbau — bis eine zweite Größe ins Spiel kommt: der Vergleich mit Produkten, die dasselbe Problem bei größerem Funktionsumfang (drei Services, sechs Mock-Typen bei eimr/evenews) schon gelöst haben. Der Rückstand wurde erst beim Nebeneinanderstellen sichtbar, nicht durch eigenes Wachstum.
Warum es mehr als unordentlich ist — die eigentliche Analyse:
- Vertrauens-/Signalkontamination. Der ganze Wert eines klinischen Entscheidungsunterstützungs-
Prototyps hängt daran, dass das, was auf dem Bildschirm steht, der tatsächlich bearbeitete Fall ist.
Ein „Löscht unwiderruflich alle Patienten"-Knopf direkt über der Patientenliste sät bei jedem Besuch
Zweifel — auch wenn er klar als Demo beschriftet ist, leiht seine räumliche Nähe zum
Alltagsablauf Glaubwürdigkeit vom einen zum anderen. Das widerspricht demselben Prinzip, das dieses
Repo an anderer Stelle durchsetzt:
GM-7existiert genau deshalb, damit keine folgenreiche Aktion beiläufig neben einer harmlosen ausgelöst werden kann. - Falsche Zielgruppe am falschen Ort. Patienten-/Auswertungsübersicht sind für Therapeuten im Gold Path gedacht, nicht für wer auch immer gerade eine Demo vorbereitet oder Testdaten zurücksetzt. Jeder Seitenbesuch zwingt zum Sortieren „ist das für mich?", obwohl die meisten Besuche keine Demo-Vorbereitung sind.
- Falsche Reifegrad-Aussage.
CLAUDE.mdist an vielen Stellen explizit gegen erfundene Vollständigkeit. Ein auffälliger Lösch-Block auf der Hauptpatientenliste behauptet implizit, diese Seite sei (auch) ein Verwaltungswerkzeug — das Gegenteil der „ehrliche, unglamouröse Prototyp"-Selbstbeschreibung, die dieses Repo sonst durchhält. - Skaliert nicht. Sobald ein zweites Demo-Werkzeug dazukommt (ein zweites Mock-Szenario, ein Seed-Knopf), zwingt Inline-Einbettung zur Wahl: überall duplizieren oder willkürlich einer Seite zuschlagen. Eine eigene Nav-Sektion skaliert, indem sie einen Listeneintrag ergänzt.
- Koppelt unabhängige Änderungstakte. Demo-Tooling ändert sich aus Gründen, die mit dem
klinischen Ablauf nichts zu tun haben (neues Cleanup-Endpoint, neues Mock-Szenario, neues
Capability-Schema). Auf
PatientUebersichtRoute/AuswertungUebersichtRoutegebündelt riskiert jede dieser Änderungen eine Seite, auf der echte Nutzer tatsächlich arbeiten.
Zweite Iteration (2026-08-15, später am Tag): die Bündelung eine Ebene tiefer auflösen
Der erste Wurf hat das Demo-Tooling aus den Fachseiten geholt und in eine Sektion „Demo" gelegt —
aber innerhalb dieser Sektion blieb genau die Bündelung stehen, die weiter oben als Problem benannt
ist: eine Seite (routes/DemodatenRoute.tsx), auf der Laden und Löschen zusammensitzen. Der
Nutzer hat das beanstandet und eine zweite, tiefere Vergleichsrunde verlangt. Ergebnis unten; die
Umsetzung ist Teil derselben Sitzung.
Was die Nachprüfung im Code ergeben hat
Alle drei Repos wurden dieses Mal Datei für Datei gelesen, nicht aus der Zusammenfassung oben übernommen.
Die zentrale Behauptung ist bestätigt. In eimr und evenews sind „Vorlagen laden/triggern" und „Testdaten löschen" getrennte Sidebar-Items, getrennte Routen, getrennte Page-Komponenten. Geteilt wird ausschließlich die Sidebar-Sektion — ein reines UI-Gruppierungskonzept.
eimr (eimr-ui/src/domains/demo) |
evenews (evenews-ui/src/domains/demo) |
|
|---|---|---|
| Items (Reihenfolge!) | Testgruppen · Demo-Vorlagen · Testdaten zurücksetzen (sidebar.ts Z. 15–17) |
Demo-Vorlagen · Mocked Services · Demodaten zurücksetzen (sidebar.ts Z. 33–37) |
| Routen | demo-tools/mocks (Z. 20) und demo-tools/cleanup (Z. 22) — zwei Einträge, zwei Elemente |
:tenantKey/blueprints (Z. 17) und :tenantKey/cleanup (Z. 16) — beide top-level, kein Präfix |
| Vorlagen-Seite | MocksListPage.tsx, 179 Z.: Tabelle, „Alle Mocks starten" (Bulk mit Polling), „Neuer Mock" |
BlueprintsOverviewPage.tsx, 323 Z.: nach Typ gruppierte Tabellen, Einzel-/Gruppen-/Auswahl-/Alle-Trigger, CRUD |
| Cleanup-Seite | CleanupPage.tsx, 187 Z.: drei Services als Schrittliste, Type-to-confirm |
CleanupPage.tsx, 138 Z.: ein Service, Zähler statt Schrittliste, Type-to-confirm |
| Berührung der beiden | keine — CleanupPage.tsx Z. 29 nennt die Mock-Vorlagen ausdrücklich als das, was nicht angefasst wird |
keine — die Blueprints-Seite verweist textlich auf „Demodaten zurücksetzen" als anderen Ort |
Zwei Ordnungs-Invarianten, die beide teilen und die dieses Repo übernimmt:
- Die unwiderrufliche Aktion steht am Ende der Sektion, nicht zwischen den harmlosen.
- Der Katalog zum Nachlesen steht vor den Aktionen (eimr: Testgruppen zuerst).
Terminologie, wörtlich (aus i18n/locales/common/de.json, eimr Z. 52–57 / evenews Z. 41–46):
sichtbares Label für die Vorlagen ist in beiden „Demo-Vorlagen"; für das Löschen sagt eimr
„Testdaten zurücksetzen", evenews „Demodaten zurücksetzen". Das Wort Cleanup erscheint in
keinem der beiden als UI-Text — nur in Code-Bezeichnern, Capability-Schlüsseln, i18n-Keys und im
URL-Segment.
DOT — die präzisierte Antwort
Die Frage war ausdrücklich, ob DOT „inzwischen doch" eine Demo-Vorlagen-UI hat, und zwar auch außerhalb
von dot-platform-ui. Nachgeprüft wurde das ganze Repo, nicht nur dieses Modul.
- Es gibt nur ein Frontend.
dot-process-hubunddot-process-repositorysind reine Maven/Java-Module ohne.tsx. Im gesamten Repo existiert genau einevite.config.tsund eineindex.html, beide indot-platform-ui. Ein „Process Hub" gibt es dort nur als Domain innerhalb dieser einen UI (src/domains/process-hub). - Cleanup-Seite: ja, bestätigt und präzisiert.
dot-platform-ui/src/domains/administration/pages/DataCleanupPage.tsx, Route:tenantKey/administration/data-cleanup(routes.tsxZ. 6), Sidebar-Label „Datenbereinigung" (sidebar.tsZ. 21, IconTrash2). Zwei destruktive Aktionen mit je eigenem Capability-Gate und je eigenem Type-to-confirm — Prozessinstanzen (Tenant-Key eintippen) und Legacy-Definitionen (PhraseLEGACY LOESCHEN). Die erste Runde oben sagte „zwei capability-gegatete Aktionen" — das stimmt. - Demo-Vorlagen-UI: nein. Kein
src/domains/demo, keine Sidebar-Sektion „Demo" (components/layout/navConfig.tsZ. 33–44 listet zehn Sektionen, keine davon), und — der stärkste Beleg — die Zeichenfolgedemokommt in keiner einzigen Datei vondot-platform-uivor (*.ts,*.tsx,*.html,*.json,*.md). Die_reinit-Endpunkte der DOT-Services werden von keiner UI-Stelle aufgerufen; erfolglos gesucht wurde außerdem nachseed|reset-|import-|Referenzfall| Beispiel|blueprint|vorlage|template|mock|musterdaten. Die einzigen „Template"-Treffer sind fachliche Positions-/Aktivitätsvorlagen der Projekt-Domäne — kein Demo-Loader. - Was DOT stattdessen hat: CLI + Doku.
DOT/DEMO_DATA.md(Abschnitt ab Z. 204),scripts/reset-odc-demo.mjs,scripts/setup-odc-enrichment.mjs,scripts/generate-odc-transactions.mjs— sie holen sich ein Keycloak-Token und rufen die_reinit-/CRUD-Endpunkte direkt gegenlocalhost:8097-8100. Serverseitig geschützt überTestDataResetService.WIPEABLE_TEST_TENANTS. - Kein neuer Stand. Der jüngste DOT-Commit ist
82cc2dacvom 2026-07-15, einen Monat alt;git log --grep=demo -iliefert keinen einschlägigen Treffer. DOT hat sich seit der ersten Runde nicht bewegt.
Die Antwort auf die Nutzerfrage, so genau wie sie geht: DOT hat das Demo-Tools-Muster nur zur Hälfte — die Lösch-Hälfte, und die nicht unter „Demo", sondern unter „Administration". Eine Demo-Vorlagen-UI hat DOT nicht und hatte sie nie; sein Lade-Werkzeug ist ein Node-Skript. „Sowohl DOT als auch evenews haben das Muster" trifft also für evenews (und eimr) vollständig zu, für DOT nur im Cleanup-Teil. Das ändert an der Schlussfolgerung nichts, sondern verstärkt sie: alle drei Produkte geben dem Löschen eine eigene Seite, und keines der drei setzt Löschen und Laden auf dieselbe Seite — DOT schon deshalb nicht, weil es die Lade-Seite gar nicht gibt.
Was daraus umgesetzt wurde
-
nav/navConfig.ts: die Sektiondemohat statt zwei jetzt drei Items, in der Reihenfolge der beiden Invarianten oben:Label Pfad Icon Testfälle :tenantKey/testfaelleListChecksReferenzfall laden :tenantKey/referenzfallDatabaseDemodaten löschen :tenantKey/demodaten-loeschenTrash2 -
Neu:
routes/ReferenzfallRoute.tsxundroutes/DemodatenLoeschenRoute.tsx.routes/DemodatenRoute.tsxist entfallen (keine dritte Zwischenschicht, keine tote Route).shell/ReferenzfallLadenButton.tsxundshell/DemoDatenLoeschenPanel.tsxsind inhaltlich unverändert — geändert hat sich nur die Seiten-/Routing-Struktur um sie herum. -
Aufgeräumte Verweise auf die entfallene Route:
App.tsx(Routenbaum-Javadoc + zwei Routen statt einer),shell/DemoDatenLoeschenPanel.tsx,routes/PatientUebersichtRoute.tsx,routes/AuswertungUebersichtRoute.tsx,tuxametrics-ui/README.md(dort stand noch, der Referenzfall-Knopf sitze „auf der Auswertungsübersicht bzw. Patientenübersicht" — seit dem ersten Wurf falsch).
Zwei bewusste Abweichungen von der Vorlage
| Vorlage | Hier | Warum |
|---|---|---|
| Label „Demo-Vorlagen" | „Referenzfall laden" | Der Plural ist dort gedeckt: eimr hat eine Tabelle mit „Neuer Mock", evenews sechs Blueprint-Typen mit CRUD. tuxametrics hat ein Szenario hinter einem POST /demo/referenzfall. Ein Menüpunkt „Demo-Vorlagen" verspräche eine Verwaltungsfläche, die es nicht gibt — dieselbe erfundene Vollständigkeit, die der Abschnitt „Nicht übernehmen" für das Grid schon ablehnt, nur im Menütext statt im Layout. „Referenzfall" ist zudem das Wort, das dieses Produkt ohnehin führt: ReferenzfallResource, init-bundle, und der Knopf selbst heißt seit jeher „Synthetischen Referenzfall laden". |
| Label „… zurücksetzen" | „Demodaten löschen" | Es wird nichts auf einen Ausgangsstand gesetzt, es wird der Fachdatenbestand geleert — ohne Sicherung, ohne Wiederherstellung. „Zurücksetzen" wäre die harmlosere Vokabel für die härtere Tat. Der Panel-Text sagt schon heute „Endgültig löschen"; das Menü sagt jetzt dasselbe. |
Unverändert übernommen bleibt dagegen kein URL-Präfix demo/ (evenews-ADR-0055) — die Sektion ist
auch hier ein reines UI-Gruppierungskonzept, und testfaelle liegt ohnehin schon flach auf
Tenant-Ebene.
Warum die erste Runde diesen Punkt verfehlt hat
Der Vergleich oben hat die Schwesterprodukte richtig beschrieben — die Zeile „Items" in der Tabelle nennt die drei getrennten Punkte beider Produkte korrekt. Übersetzt wurde daraus aber nur die Sektion, nicht die Auftrennung darin: der Umsetzungsplan (Schritt 2) schrieb „Demodaten-Seite" im Singular und niemand hat die Zeile gegen die eigene Belegtabelle gehalten. Ursache ist dieselbe wie Punkt 4 in „Warum Test-/Demo-Elemente überhaupt auf Fachseiten landeten": zwei Knöpfe fühlen sich zu klein für zwei Seiten an. Das Argument ist auch hier falsch, und zwar aus demselben Grund — die Seitenzahl bemisst sich nicht am Platzbedarf, sondern daran, ob zwei Handlungen dieselbe Absicht haben. „Vorführdaten anlegen" und „Mandant unwiderruflich leerräumen" haben das nicht.
Dritte Iteration (2026-08-15, abends): aus „Referenzfall laden" werden „Demo-Vorlagen" — mit echten Vorlagen
Die zweite Iteration hat die Sektion richtig aufgeteilt, aber am Vorlagen-Punkt eine Abweichung
festgehalten und ausführlich begründet: Label „Referenzfall laden" statt eimrs/evenews'
„Demo-Vorlagen", weil tuxametrics „genau ein Szenario hinter genau einem POST /demo/referenzfall" habe und ein Plural-Menüpunkt eine Verwaltungsfläche verspräche, die es nicht
gibt. Diese Begründung war richtig und ist jetzt gegenstandslos — nicht weil sie umgangen wurde,
sondern weil die Voraussetzung entfallen ist: es gibt seit dieser Iteration drei ausgearbeitete
Szenarien.
Nutzerauftrag war ausdrücklich beides: (a) wirklich mehr ladbare Szenarien, nicht nur strukturelle Vorbereitung, und (b) eine Seite, die auf mehrere ausgelegt ist. Ausdrücklich nicht gewählt wurde eine reine „was liegt an Demodaten herum"-Ansicht.
Der heikle Teil: welche Konstellationen — und warum nicht einfach zwei weitere
Das ist die Stelle, an der dieses Thema die Kernregel des Repos berührt (CLAUDE.md: „Wo das
Material keine Zahl hat, hat der Code auch keine"). FACH-109 benennt 13 Konstellationen, von
denen bis heute eine ausgearbeitet war; die übrigen zwölf sind „benannt, aber nicht
ausgearbeitet — keine Eingangswerte, keine erwarteten und keine ausdrücklich nicht erwarteten
Ergebnisse" (OF-41 / E-18, blockierend, in v1.2 unverändert offen).
Recherchebefund, der die Auswahl entschieden hat: Die Annahme „zu den anderen zwölf gibt es gar
nichts" stimmt so nicht. tuxamed Bearbeitet/testfaelle/ überführt alle 13 Konstellationen in
benannte Testfälle (00-uebersicht.md Z. 76–89), und für zwei davon steht dort eine ausgearbeitete
Positiv- und eine ausdrückliche Negativerwartung: TC-AUS-008 und TC-AUS-009 in
04-fachliche-auswertung.md tragen je ein pruefung- und ein darfNichtEntstehen-Feld. Genau
das ist das Akzeptanzkriterium aus FACH-109 („Ein Referenzfall ohne Negativerwartung prüft nur die
Funktion, nicht die Sicherheit"). Was dort weiterhin fehlt, sind Zahlen — und die müssen auch
nicht von dort kommen (siehe unten).
Gewählt wurden deshalb Konstellation 4 und 5: derselbe kritische Kaliumwert, einmal mit und einmal ohne Hämolysehinweis.
| Kriterium | Warum 4 und 5 |
|---|---|
| Am wenigsten erfunden | Die einzigen zwei der verbleibenden zwölf mit ausformulierter Negativerwartung im Material. |
| Anderes strukturelles Verhalten als Konstellation 2 | Konstellation 4 erzeugt ein Finding ohne Ebene (PLAUSIBILITAETS_ODER_PRAEANALYTIKHINWEIS, ebene() == null, FACH-046 Z. 1085) — den einzigen solchen Zustand im Produkt. Konstellation 5 erzeugt R3 + sicherheitsstatus: kritischer-befund-offen. Konstellation 2 erreicht keinen von beiden. |
| Sie sind ein Paar | Die beiden Bundles unterscheiden sich in einem Feld: praeanalytik.haemolysehinweis. Einzeln geladen zeigt keiner von beiden die Regel; erst der Vergleich zeigt, was FACH-045 Z. 1057 meint („der kritische Wert wird vor Auslösung des Hinweises gegen Präanalytik geprüft"). Das ist der Grund, warum das Kontingent „maximal zwei" hier auf ein Thema statt auf zwei ging. |
| Bisher totes Codestück | Der Zweig kaliumHochUndHaemolytisch in AuswertungslaufService war von keinem Demodatensatz je erreichbar. |
Keine neue Fachzahl — die Bauregel im Klartext:
| Herkunft | |
|---|---|
| Patient, Messwert (6,4 mmol/l), Referenzbereich ([3,5; 5,1]), Kreatinin | erfunden, wie in Konstellation 2 (OF-45: es gibt kein Echtmaterial) |
| Die Schwelle, gegen die sie laufen (Kalium kritisch > 6,0 mmol/l) | belegt: Regelkatalog.KRITISCHE_SCHWELLEN, FACH-045 Z. 1140, entschieden in v1.2 (E-8) |
Die Platzhalterzahlen sind zusätzlich wörtlich aus dem bestehenden Test
SicherheitUndScopeGateTest#kaliumMitHaemolyse_erzeugtProbenhinweis übernommen statt neu erfunden —
dieselbe Konstellation hat im Repo damit genau eine Zahlenfassung.
Was ausdrücklich nicht gebaut wurde und nie gebaut wird: Konstellation 12 („Auffälliges
Verhältnismuster ohne Einzelwertauffälligkeit") ist laut FACH-109 eine E2-Konstellation. Sie
zu bauen hieße, Leitplanke 3 zu brechen. Sie ist damit die einzige der 13, die dieses Repo dauerhaft
nicht abdecken kann — das steht jetzt im Javadoc von ReferenzfallService, in
init-bundle/README.md und auf der Seite selbst, damit „3 von 13" nicht als bloßer Rückstand
gelesen wird.
Ein Befund, der nebenbei entstand — und bewusst NICHT gefixt wurde
TC-AUS-008 verlangt neben „kein Eskalationshinweis" auch „keine Kaliumaussage". Der
Auswertungslauf erzeugt bei Hämolyse zwar korrekt den Probenhinweis statt des kritischen Befunds,
legt für Kalium aber trotzdem ein E3-Finding einzelwertauffaelligkeit an — erzeugeE3Findings()
kennt den Präanalytikhinweis nicht. Das Javadoc von Praeanalytik.java behauptet im selben Repo
bereits das Gegenteil („Interpretation und jede Kaliumaussage werden zurückgehalten").
Das ist eine bestehende Lücke des Auswertungslaufs, keine Eigenschaft der neuen Bundles — sie war
nur nie sichtbar, weil kein Demodatensatz diesen Pfad je erreichte; auch der vorhandene Test prüft
ausschließlich die E1-Seite. Sie zu schließen wäre eine Änderung am fachlichen Verhalten und
braucht eine eigene Entscheidung, keinen Commit nebenbei. Bis dahin steht sie als erwartung.abweichung
in praxis01-referenzfall-04.json. Der Referenzfall macht die Lücke sichtbar — das ist mehr wert als
ein Bundle, das sie umgeht.
Was umgesetzt wurde
Backend (tuxametrics-laborauswertung-service) — erstmals in dieser Themenreihe ein
Backend-Eingriff; die ersten beiden Iterationen kamen ohne aus:
- Neu:
init-bundle/praxis01-referenzfall-04.json,praxis01-referenzfall-05.json.praxis01-referenzfall-02.jsonbekommt nur die vier Katalogfelder (titel,kurzbeschreibung,konstellation,testfallId) — inhaltlich unverändert. ReferenzfallService: EnumSzenario(Schlüssel + Dateipfad, mehr nicht),lade(tenantKey, szenarioKey),szenarien(). Kein Duplikat der Anzeigetexte: Titel und Kurzbeschreibung liest der Katalog aus den Bundles selbst — ein Szenario ist an genau einer Stelle beschrieben, ein neues Bundle erscheint ohne Frontend-Änderung.- Der Bearbeitungsschritt auf der Sicherheitsebene läuft jetzt nur, wenn das Bundle eine Begründung
mitbringt. Bei Konstellation 5 ist der offene
E1-Punkt das erwartete Ergebnis; ein Loader, der ihn ungefragt wegräumt, würde die Eskalation löschen, die der Fall zeigen soll — und wäre die falsche Seite vonGM-7. ReferenzfallResource:GET .../demo/referenzfall(Katalog) undPOST .../demo/referenzfall/{szenarioKey}. Der parameterlosePOSTbleibt unverändert und lädt weiter Konstellation 2 — er wird auch aus dem Testfallkatalog gerufen.- Kein neuer Capability-Schlüssel. Alles läuft über
txm.demo.load;CapabilityRegistrarist im Diff dieser Iteration nicht enthalten. Der Szenarienkatalog ist die Auswahlliste des Ladens und enthält keine Mandantendaten, sondern drei Titel aus mitgelieferten Dateien — ein eigener Schlüssel bildete keine Entscheidung ab, die jemand treffen wollte. Nebenbefund beim Deploy, nicht von dieser Iteration verursacht: der Registrar meldet beim Start 19txm.*-Schlüssel,CLAUDE.mdnennt weiterhin 18. Die Abweichung stammt aus dem Process-Hub-Wiederanschluss desselben Tages (vier neuetxm.process.*) und ist hier nur festgehalten, nicht korrigiert. - Neu:
ReferenzfallKaliumpaarTest(7 Tests) — prüft beide Fälle, jede Negativerwartung einzeln, die Differenz des Paares, den 404 bei unbekanntem Schlüssel und die Unverändertheit des parameterlosen Aufrufs.
Frontend (tuxametrics-ui):
routes/ReferenzfallRoute.tsx→routes/DemoVorlagenRoute.tsx, Route:tenantKey/referenzfall→:tenantKey/demo-vorlagen.shell/ReferenzfallLadenButton.tsx→shell/DemoVorlagenListe.tsx(Karten-Grid, je Karte Titel, Kurzbeschreibung, Konstellation, verlinkter Testfall, „Starten").navConfig.ts: „Referenzfall laden" → „Demo-Vorlagen". Die alte Abweichungs-Begründung ist nicht gelöscht, sondern als erledigt markiert — sonst liest der nächste Leser einen Widerspruch.- Kein Redirect für die alte Route. Sie war zum Zeitpunkt der Umbenennung wenige Stunden alt
(zweite Iteration desselben Tages), stand in keiner externen Verlinkung und ist ersatzlos entfallen.
Ein Redirect wäre hier Ritual, keine Rückwärtskompatibilität.
App.tsxundnavConfig.tssind konsistent, es bleibt keine tote Route. - Kein Sprung mehr in die erzeugte Auswertung. Der alte Einzelknopf navigierte sofort dorthin —
richtig bei einem Fall. Weil 4 und 5 ihre Aussage erst im Vergleich entfalten, bleibt der Link
jetzt an der Karte stehen (Muster
TestfallAusfuehren), statt den Nutzer aus der Liste zu werfen. MOCK_SZENARIENinshell/TestfallAusfuehren.tsxist vonRecord<string, true>aufRecord<string, string>umgestellt und bildet jetzt drei Testfälle auf ihren jeweiligen Szenarioschlüssel ab (TC-AUS-013,TC-AUS-008,TC-AUS-009). „Ausführen" lädt damit den Fall, der zum Testfall gehört, statt überall denselben. Von 63 auf 60 Fälle ohne Mock-Szenario.
Was an der Haltung dieses Dokuments unverändert gilt
- Keine erfundene Vollständigkeit. Die Seite schreibt „3 von 13" hin und benennt, dass eine der
zehn fehlenden (
E2) nie kommt. Kein „weitere folgen". - Kein
PageHeader(Schritt 4) und kein capability-bewusstes Deaktivieren (Schritt 5). Beide bleiben offen; diese Iteration hat sie erneut nicht angefasst. - Keine Verwaltungsfläche. Anlegen, sonst nichts — kein CRUD, kein „Neue Vorlage", kein Bulk-Run. Die Absage an eimrs/evenews' Mock-Verwaltung im Abschnitt „Nicht übernehmen" gilt unverändert; nur die Absage an das Grid ist hinfällig, weil sie ausdrücklich mit „es gibt ein ausgearbeitetes Szenario" begründet war.
Was offen bleibt
| Punkt | Warum |
|---|---|
Geändert in der dritten Iteration: TC-AUS-008 und TC-AUS-009 haben seit 2026-08-15 eigene Szenarien. Die verbleibenden 60 sind unverändert fachlicher Ausarbeitungsaufwand (init-bundle-Datensätze je Fall), kein Verdrahtungsproblem — siehe testmanagement-integration.md. |
|
| 10 von 13 Referenzfall-Konstellationen ohne Bundle | Neu benannt in der dritten Iteration. Neun davon sind baubar und warten nur auf Arbeit; die zehnte (Konstellation 12, auffälliges Verhältnismuster) ist eine E2-Konstellation und wird in diesem Repo nie entstehen (Leitplanke 3, OF-01/E-7). Wer die Zahl „3 von 13" als reinen Rückstand liest, liest sie falsch. |
erzeugeE3Findings() kennt den Präanalytikhinweis nicht |
Neu gefunden in der dritten Iteration und bewusst nicht behoben: Änderung am fachlichen Verhalten, braucht eine eigene Entscheidung. Ausführlich oben unter „Ein Befund, der nebenbei entstand". |
| Katalog seit v1.1, nicht auf v1.2 nachgezogen | Unverändert, siehe testabdeckung-gold-path.md. |
PageHeader nur auf vier Seiten |
Bewusst begrenzt, siehe Schritt 4. Produktweiter Rollout = eigenes Thema. |
| Nicht verifiziert | Der visuelle Endzustand. Diese Analyse ist ausschließlich Code-Lektüre — es wurde nichts gestartet und nichts verglichen als laufende Oberfläche. Ob die Bündelung im Betrieb tatsächlich besser wirkt, zeigt erst ein Deploy. |
Unangetastet: TUXAMETRICS_REGULATORIK_EINSTUFUNG und TUXAMETRICS_PILOT_BETRIEBSMODUS bleiben
UNGEKLAERT, RegulatorikGuard ist nicht berührt. Kein neuer Capability-Schlüssel, keine neue
Fachzahl, kein neuer Enum-Wert, kein Backend-Eingriff in irgendeinem der sechs Schritte.
Präzisierung nach der dritten Iteration (2026-08-15): Der letzte Halbsatz gilt nur noch für die Iterationen 1 und 2. Die dritte hat sehr wohl ins Backend eingegriffen (zwei Bundles, Szenario-Enum, zwei Endpunkte). Alles andere bleibt wörtlich richtig, und das ist hier der Punkt: kein neuer Capability-Schlüssel (
CapabilityRegistrarist im Diff nicht enthalten — Nebenbefund: er meldet inzwischen 19 statt der inCLAUDE.mdgenannten 18, eine Abweichung aus dem Process-Hub-Wiederanschluss desselben Tages, nicht aus dieser Session), keine neue Fachzahl (die einzige beteiligte Schwelle stand schon imRegelkatalog), kein neuer Enum-Wert im Domänenmodell, keineE2, keinRegulatorikGuard. Der einzige neue Enum istReferenzfallService.Szenario— eine Liste von drei Dateipfaden, kein fachliches Konzept.
Vierte Iteration (2026-08-16): aus dem Karten-Grid wird eine Tabelle mit Detailseite
Dieser Abschnitt steht bewusst nach „Was offen bleibt" und ist der jüngste — es gilt weiterhin der Lesehinweis am Dateikopf: bei Widersprüchen gilt der spätere Abschnitt.
Nutzervorgabe, sinngemäß: in eimr wie in DOT sind das normale Tabellen mit Detailseite; baue es hier auch so — was, wenn morgen zwanzig weitere Samples dazukommen? Das Argument entscheidet die Sache, und zwar unabhängig davon, wie die drei heutigen Karten aussehen: ein Grid trägt drei Einträge gut und zwanzig gar nicht. Jede Karte wiederholt dieselben vier Beschriftungen („Konstellation:", „Testfall:", „Starten"), und zwei Fälle lassen sich nur vergleichen, wenn ihre Konstellation untereinander in einer Spalte steht — was bei den Konstellationen 4 und 5 genau der Zweck ist.
Was die Nachprüfung in eimr und DOT ergeben hat
| eimr | DOT | |
|---|---|---|
| Fundstelle | eimr-ui/src/domains/demo/pages/MocksListPage.tsx → MockDetailPage.tsx |
u. a. dot-platform-ui/src/domains/finance/pages/CustomersPage.tsx → CustomerDetailPage.tsx, domains/xrm/.../OrganizationTable.tsx, domains/project-economy/.../ProjectTable.tsx |
| Struktur | div.rounded-xl border overflow-hidden › table.w-full text-sm › thead.bg-muted/30 border-b › tr mit onClick={() => navigate(...)} + cursor-pointer hover:bg-accent/20 › ChevronRight-Spalte |
div.border rounded-lg overflow-hidden › table.w-full text-sm › tr.border-b bg-muted/50 › tbody.divide-y divide-border › tr mit onClick/cursor-pointer hover:bg-muted/30 |
| Sortierung | keine | ja, lokale SortHeader-Komponente — pro Seite dupliziert, sortiert nur die geladene Seite |
| Gemeinsames Table-Component | nein | nein — shared-kernel/ui hat Tag, Pill, ListToolbar, Pagination, aber kein Table/DataTable. Jede Domain baut ihre <table> selbst (ADR-0003 dort: {Entity}Badge/Row/Table/Detail pro Domain) |
| Nested-Klick-Schutz | ja | ja — onClick={e => e.stopPropagation()} auf Links/Buttons in Zellen |
Korrektur einer Annahme aus der Auftragsstellung: DataCleanupPage.tsx ist in DOT kein
Tabellen-Muster, sondern eine Formular-/Aktionsseite mit zwei Danger-Cards und Type-to-confirm — das
deckt sich mit dem Befund der zweiten Iteration oben. Das DOT-Tabellenmuster steht in Finance/XRM/
Project-Economy, nicht in Administration.
Übernommen wurde die Form, nicht das Markup. Beide Vorbilder stimmen in Struktur und
Verhalten überein (Wrapper mit overflow-hidden › table.w-full text-sm › klickbare Zeile ›
stopPropagation innen), unterscheiden sich aber in den Tailwind-Tokens. Die hiesige Tabelle folgt
deshalb domains/testfaelle/components/TestCaseTable.tsx — dieselbe Form, aber mit den Tokens, die
dieses Produkt bereits verwendet (bg-accent/40, border-border, hover:bg-accent/30). Ein
zweites Tabellen-Aussehen im selben Repo wäre der teurere Weg zur selben Sache.
Was umgesetzt wurde — Frontend only, kein Backend-Eingriff
shell/DemoVorlagenListe.tsx: Karten-Grid → Tabelle. Spalten Vorlage (Titel als echterLink+ Kurzbeschreibung darunter), Konstellation, Testfall (verlinkt wie bisher), Standard,ChevronRight. Zeilenklick navigiert; die FunktionDemoVorlageKarteist entfallen.- Neu:
shell/DemoVorlageDetail.tsx+ dünner Adapterroutes/DemoVorlageDetailRoute.tsx, Route:tenantKey/demo-vorlagen/:szenarioKeyinApp.tsx. Trägt Herkunft, „Starten" und das Erfolg/Fehler-Feedback — die Mutation ist 1:1 aus der Karte übernommen, inklusiveinvalidateQueries()und des Verzichts auf den Sprung in die erzeugte Auswertung. navConfig.ts: „Demo-Vorlagen" vonend: trueaufend: false, damit die Sidebar auf der Detailseite aktiv bleibt (dieselbe Begründung, die dort schon bei „Board" und „Prozesse" steht).- Doku-Nachzug in
App.tsx(Routenbaum-Javadoc) unddomains/testfaelle/pages/TestfallDetailPage.tsx(dessen Javadoc verwies auf die entfallene Karte).
Kein neuer Endpunkt, keine neue Property. Die Detailseite liest denselben Szenarienkatalog wie
die Liste (GET .../demo/referenzfall, gleicher Query-Key → Cache-Treffer statt zweitem Netzaufruf)
und sucht den Schlüssel darin. Ein GET .../demo/referenzfall/{key} wäre derselbe Inhalt ein zweites
Mal. Angezeigt werden genau die sieben Felder von ReferenzfallSzenario — auch synthetisch
(immer true, OF-45) und standard, beide im Klartext statt als Häkchen. Nutzervorgabe war
ausdrücklich, die Seite lieber dünn zu lassen als das Backend für optische Substanz zu erweitern;
das ist auch die ehrlichere Variante.
Drei bewusste Auslassungen
| Nicht gebaut | Warum |
|---|---|
| Sortierbare Spalten (DOT hat sie, eimr nicht) | Drei Zeilen. Eine Sortierfunktion über drei Zeilen ist dieselbe Sorte Theater wie die abgelehnte Fortschrittsliste mit einem Schritt. Rückweg, falls die Liste zweistellig wird: DOTs SortHeader ist ~15 Zeilen und dort ohnehin pro Seite kopiert. |
Suche / ListToolbar / Pagination |
Dito — der Katalog ist eine Liste mitgelieferter Dateien, kein Datenbestand, und das Backend paginiert ihn nicht. |
| Ein „Starten"-Knopf pro Zeile | Der Grund für den Knopf auf der Karte war, dass das Ergebnis dort stehen bleiben musste, wo geklickt wurde. Auf einer Detailseite ist diese Zuordnung trivial gegeben. Bei zwanzig Zeilen wären es zwanzig Aufforderungen, den Mandanten vollzuschreiben. |
Tastaturzugänglichkeit ist der eine Punkt, an dem hier über die Vorlage hinausgegangen wurde:
eimr und DOT machen die Zeile ausschließlich per onClick klickbar, damit ist die Detailseite ohne
Maus unerreichbar. Hier ist der Titel zusätzlich ein echter <Link> (mit stopPropagation, sonst
navigierten Link und Zeilen-Handler zweimal).
Status
npm run typecheck grün. Deployt auf die Alcatraz-VM (192.168.8.113) als einziger neu
gestarteter Container (docker compose up -d --no-deps tuxametrics-ui) — tuxametrics-ui läuft,
nginx-Log ohne Fehler, HTTPS antwortet mit 200, alle Nachbar-Container unberührt (Uptimes
unverändert). Nicht verifiziert bleibt — wie in allen vorigen Iterationen — der visuelle
Endzustand im Browser; geprüft wurde, dass die Seite ausgeliefert wird, nicht wie sie aussieht.
Fünfte Iteration (2026-08-16, später): die Detailseite zeigt die Werte
Jüngster Abschnitt. Er widerruft eine Entscheidung, die vier Absätze weiter oben noch als „die ehrlichere Variante" steht — das ist der Grund, warum er ausführlich begründet ist und nicht bloß den alten Text überschreibt.
Nutzerbefund, wörtlich: „na ja ich möchte ja die werte sehen". Die vierte Iteration hatte die Detailseite bewusst auf die sieben Katalogfelder beschränkt, mit zwei Argumenten: das Backend nicht für optische Substanz erweitern, und keine zweite fachliche Wahrheit neben dem Regelwerk erzeugen.
Das erste Argument war falsch angewandt. Die Werte einer Demo-Vorlage sind keine Optik — sie sind das, was die Vorlage ist. Wer eine Laborbefund-Vorlage auswählt, wählt einen Laborbefund; Titel und Kurzbeschreibung sind sein Etikett, nicht sein Inhalt. Bis heute war der Inhalt nur sichtbar, indem man den Fall anlegte — also durch genau den Schritt, für den man sich vorher entscheiden wollte. Das ist keine dünn gehaltene Seite, das ist eine Seite ohne ihren Gegenstand.
Das zweite Argument gilt weiter und ist die Grenze der Änderung. Gezeigt werden die Eingangswerte des Bundles. Nicht gezeigt wird, was daraus entsteht — kein Finding, keine Empfehlung, kein Sperrgrund, keine Risikoklasse. Das sagt der Auswertungslauf und steht im verlinkten Testfall. Eine Vorschau, die Ergebnisse vorwegnimmt, wäre die zweite fachliche Wahrheit, gegen die die vierte Iteration richtigerweise argumentiert hat.
Warum das eine echte Backend-Änderung sein musste
Die Werte lagen serverseitig längst in init-bundle/praxis01-referenzfall-{02,04,05}.json, waren
aber über keinen Endpunkt lesbar: ReferenzfallService las die Bundles nur im Schreibpfad
(lade()) und verwandelte sie dort sofort in Entitäten. Ein reiner Vorschau-Read existierte nicht.
Anders als in den Iterationen 1, 2 und 4 war das hier also nicht vermeidbar — Frontend-only hätte
bedeutet, die Werte im Frontend zu wiederholen, und damit hätte dasselbe Szenario zwei Quellen.
Genau das verhindert ReferenzfallSzenario seit der dritten Iteration ausdrücklich.
Entscheidungen
| Frage | Entscheidung | Verworfene Alternative |
|---|---|---|
Eigener Detail-Endpunkt GET .../demo/referenzfall/{key}? |
Nein — die Werte hängen am bestehenden Katalog. Drei Dateien, zusammen zwölf Messwerte; der Sprung Liste → Detail bleibt ein Cache-Treffer auf ['demo','szenarien',tenantKey]. |
Ein zweiter Endpunkt hätte einen zweiten Query-Key, einen zweiten Ladezustand und einen zweiten Netzaufruf für dieselben wenigen Kilobyte gekostet. Bei zwanzig Bundles wäre die Abwägung neu zu treffen — dann trägt die Liste zwanzig Befunde. |
Die *Create-Records direkt ausliefern? |
Nein, eigene Vorschau*-Records in ReferenzfallSzenario. |
MesswertCreate trägt Felder, die beschreiben, wie ein Wert ins System kam (normalisierterWert, angewandterFaktor, erkennungsunsicherheit, erfassungsart, bestimmungsgrenze), nicht welchen Wert der Fall setzt. Welche Felder die Vorschau zeigt, soll eine Entscheidung sein und keine Nebenwirkung eines Eingabeformats. |
| Nur Messwerte, wie im Auftrag als Minimum genannt? | Nein — zusätzlich Patient, Befundkopf/Präanalytik, Sicherheitsmerkmale, Supplemente, Medikation. | Mit nur Messwerten wären die Vorschauen der Konstellationen 4 und 5 zeichengleich: derselbe Kaliumwert 6,4 mmol/l, derselbe Referenzbereich. Ihr einziger Unterschied ist praeanalytik.haemolysehinweis — das Feld, das zwischen Probenhinweis und Notfallhinweis entscheidet (FACH-045 Z. 1057). Eine Vorschau ohne diesen Block hätte zwei identische Fälle gezeigt und die Aussage des Paars zerstört. |
| Leere Kategorien ausblenden? | Nein, sie stehen mit Zähler (0) und einem Satz da. |
Dass Konstellation 4 keine Medikation und keine Supplemente trägt, ist eine Aussage über den Fall — er isoliert eine einzige Regel — und keine fehlende Angabe, die man verbergen sollte. |
Zwei Stellen, an denen die Vorschau bewusst unbequem ist
interaktionspruefungsteht in der Vorschau, obwohl kein Bundle das Feld setzen kann (MedikationseintragCreatehat es nicht). Es kommt aus dem Enum mit seinem einzigen Wertnicht-automatisiert-geprueft, dazu der Klartext ausMedikationseintrag.HINWEIS_NICHT_GEPRUEFT— dieselbe Formulierung wie an der erzeugten Auswertung, eine Quelle. Leitplanke 4 (OF-07) soll schon vor dem Anlegen sichtbar sein, nicht erst danach.- Ein offener elementarer Gehalt bleibt offen. Das Zinkbisglycinat in Konstellation 2 trägt
elementarerGehalt: nullmit Quelleoffen; die Tabelle schreibt „offen — kein Standardwert unterstellt" statt einer leeren Zelle (FACH-022, Z. 606). Eine leere Zelle sähe aus wie ein Versäumnis.
Was umgesetzt wurde
model/ReferenzfallSzenario.java: sechs neue Felder (patient,befund,messwerte,sicherheitsmerkmale,supplemente,medikation) und sechs geschachtelteVorschau*-Records, je mit@RegisterForReflection— das native Image ist bei diesem Service zweimal an Serialisierung gescheitert, die Registrierung ist billige Versicherung.service/ReferenzfallService.java:szenarien()bildet die bereits geparsten Bundles ab. Der Lesevorgang ist derselbe wie vorher — die Bundles wurden hier immer schon vollständig gelesen.oderLeer()gilt nur für den Katalog: ein Bundle ohnemesswertesoll beim Laden weiterhin scheitern (ein Referenzfall ohne Messwerte ist ein Fehler), aber nicht die Navigation für alle drei Fälle mitnehmen.web/ReferenzfallResource.java: Javadoc nachgezogen. Die Aussage „enthält keine Mandantendaten" gilt unverändert — es sind dieselben drei Dateien, nur vollständiger gelesen; aus der Datenbank kommt nach wie vor nichts, und der Zugriff bleibt hintertxm.demo.load.- Test
ReferenzfallKaliumpaarTest: zwei neue Fälle — der Katalog liefert die Werte (inkl. offenem elementarem Gehalt, Interaktionsstatus,betroffeneInterventionaus dem Katalog-Enum), und die Vorschauen von 4 und 5 unterscheiden sich in genau einem Feld bei ansonsten leeren, aber vorhandenen Listen. - Frontend: sechs neue Interfaces in
domains/auswertung/model/auswertung.ts(+ Barrel-Export),shell/DemoVorlageDetail.tsxum sechs Abschnitte erweitert. Die Messwert-Tabelle folgtdomains/auswertung/components/MesswertTable.tsxin Aussehen und Haltung: ein fehlender Referenzbereich wird benannt statt ergänzt (FACH-030), ein Zustand nicht durch eine Zahl ersetzt (FACH-035).
Was hier nicht passiert ist
Kein neuer Capability-Schlüssel (die Vorschau hängt an txm.demo.load — wer den Fall nicht anlegen
darf, sieht auch nicht, was er anlegen würde), keine neue Fachzahl (jede angezeigte Zahl stand
schon vorher in ihrer Bundle-Datei), kein neuer Enum-Wert, keine E2, RegulatorikGuard
unberührt. GM-7 ist wie in allen Iterationen dieses Themas nicht betroffen: eine Demo-Vorlage
anzusehen ist keine klinische Entscheidung.
Status
mvn -f tuxametrics-laborauswertung-service/pom.xml test grün (67 Tests), npm run typecheck grün.
Nativer Bau des Laborauswertung-Service (4 m 52 s, native-image-xmx=6g unverändert, kein Exit 137)
plus Frontend-Bau, beide auf die Alcatraz-VM deployt
(docker compose -f docker-compose.yml -f docker-compose.native.yml up -d --no-deps tuxametrics-laborauswertung-service tuxametrics-ui). Container healthy bzw. nginx sauber, native
Startzeit 0,088 s, 19 txm.*-Capabilities registriert, kein Reflection-/Serialisierungsfehler
beim Start.
Zwei Dinge sind nicht verifiziert, und das eine ist neu:
- der visuelle Endzustand im Browser — wie in allen vorigen Iterationen;
- die serialisierte Antwort des Katalogs gegen das native Image. Der Endpunkt ist erreichbar und
weist korrekt ab (
403 no_grant), aber der Guard läuft vor dem Methodenrumpf — ein Aufruf mit Grant war nicht möglich, weil im Realm für alle ClientsdirectAccessGrantsEnabled: falsesteht und das einzige beschaffbare Token (Service-Accounttuxametrics-services) keinentxm.demo.load-Grant hat. Einen Grant dafür anzulegen wäre eine Änderung am Autorisierungsstand der VM und keine Nebensache. Exerziert ist der Serialisierungspfad damit nur im JVM-Testlauf; für das native Image tragen alle sechsVorschau*-Records@RegisterForReflection. Restrisiko klein, aber benannt — es hat sich bei genau diesem Service schon zweimal materialisiert.