konzept vertraulich owner: matus
Service-Landschaft
Service-Landschaft
Key: PG-DOMAINS-0001 · Domain: Projekt · siehe ../INDEX.md
Eigene Bausteine
| Baustein | Art | Port | Zweck |
|---|---|---|---|
tuxametrics-platform-service |
Quarkus Data Service (plt) |
8125 | Die Capability-Authority (GG-ARCH-SERVICES-0005, Form „eigen"): Tenant (= Praxis), Capability-Katalog inkl. allowedActors, CapabilityGrant. Check-Endpunkt für jeden CapabilityGuard. Wire-Vertrag: CAPABILITY_CHECK_CONTRACT.md |
tuxametrics-virtual-identity-service |
Quarkus Data Service (vid) |
8126 | Identity je Praxis: Personen, Funktionspostfächer und agentische Identitäten. REST /api/vid/v1, MCP nur lesend. Capability-Konsument, nicht Authority |
tuxametrics-substanzstammdaten-service |
Quarkus Data Service (sub) |
8128 | Referenzkatalog Wirkstoff ← Handelsname (Medikament/Supplement). REST /api/substanz/v1, MCP nur lesend. Der einzige Fachdatenbestand dieses Produkts ohne Patientenbezug — und ohne Mandanten: alle Zeilen tragen den Sentinel platform, die API ist trotzdem tenant-skopiert (Sicherheitsgrund, siehe ADR-0012 §3). Löst Handelsname → Wirkstoff auf, schaltet damit keine Interaktionsprüfung frei |
tuxametrics-laborauswertung-service |
Quarkus Data Service (txm) |
8120 | Der gesamte Gold Path: Patient, Auswertung, Intake, Findings, Therapieplan, Freigabe, Bericht. REST /api/txm/v1, MCP /mcp (nur lesend) |
tuxametrics-ui |
React/TS, App auf @zwirn/web |
5173 (dev) | Slices entlang des Ablaufs plus App-Gerüst (Router, Auth, Nav) |
tuxametrics-process-hub-cockpit |
Spring Boot + Flowable 8 | 8124 | /process-api/** für das Prozess-Cockpit. Dünner Wrapper um dev.zwirn:zwirn-process-hub-flowable-spring, kein Fachcode. Die eine dokumentierte Ausnahme vom Quarkus-Standard (Zwirn-ADR-0007) — und die eine benannte Ausnahme von GG-DEVOPS-0003: bleibt bewusst JVM |
tuxametrics-keycloak |
Keycloak 26.1, Realm digital-labs |
8180 | Der IdP. Beantwortet ausschließlich wer bist du; was darfst du beantwortet der platform-service (GG-GOV-SECURITY-0003). Clients und Claim-Mapper: keycloak/README.md |
tuxametrics-db |
Postgres 18 | 5520 | Eigene DB, nur der Laborauswertungs-Service |
tuxametrics-platform-db |
Postgres 18 | 5524 | Eigene DB der Authority |
tuxametrics-vid-db |
Postgres 18 | 5525 | Eigene DB der Virtual Identity |
tuxametrics-substanz-db |
Postgres 18 | 5528 | Eigene DB des Substanzkatalogs. Die Trennung von tuxametrics-db ist die Entscheidung: der Bestand soll perspektivisch durch eine offizielle externe Arzneimitteldatenbank ersetzbar sein, und das darf keine Operation an Befunden und Freigaben werden |
tuxametrics-auth-db |
Postgres 18 | 5526 | Keycloaks eigene DB — sonst läge der Realm auf einer H2-Datei im Container |
tuxametrics-process-hub-db |
Postgres 18 | 5523 | Flowable-Engine-DB des Cockpits. Enthält seit 2026-08-12 eine Definition (das Dokumentationsmodell des Gold Path) und keine Instanz |
opa |
OPA-Policy-Bundle (Zwirn-ADR-0005) | 8181 | An der Capability-Entscheidung nicht beteiligt. Der platform-service entscheidet in Java; GG-ARCH-SERVICES-0005 nennt „Kein OPA-Zwang" als eigene Abgrenzung. Der Container stammt aus der Zeit vor der Authority — ihn zu entfernen ist eine eigene kleine Entscheidung |
Mandantenschlüssel: platform ist der Sentinel für plattformweite Aggregate und Grants
(util/PlatformScope) — kein echter Mandant. Seit 2026-08-26 hat er einen zweiten Nutzer außerhalb
der Authority: den Substanzkatalog (util/SubstanzScope, ADR-0012). Das ist bewusst dieselbe Zeichenkette
und keine zweite Konvention — beide Male heißt sie „gehört keiner Praxis". praxis01 ist der synthetische Demo-Mandant des
Referenzfalls. Beide haben genau 8 Zeichen; das ist die harte Obergrenze aus GG-GOV-SECURITY-0005.
Betriebene Brainversum-Quelle (seit 2026-08-26)
Eine eigenständige brainversum-Instanz mit genau einer Quelle:
der Dokumentation dieses Repos (56 Markdown-Dateien). Drei Prozesse auf einem Image, betrieben auf
tuxametrics-vm. Umfang, Begründungen und Betrieb:
../../brainversum/README.md.
| Baustein | Art | Port | Zweck |
|---|---|---|---|
tuxametrics-brainversum-ingest |
brainversum (Python 3.13) | — | Liest den kuratierten Markdown-Baum alle 300 s in einen SQLite-Graphen (brainversum daemon). Kein veröffentlichter Port |
tuxametrics-brainversum-web |
brainversum (Python 3.13) | 8135 | Durchsuchbare Oberfläche auf den Graphen. Volltext über FTS5/BM25 |
tuxametrics-brainversum-mcp |
brainversum (Python 3.13) | 8136 | MCP-Server (streamable-http, /mcp) — derselbe Bestand für einen Agenten. Nur lesend |
Sie gehören nicht zum Gold Path, und die Portlücke zu 8120–8128 zeigt das. Diese drei
Container sprechen mit keinem anderen Service dieses Stacks: keine Datenbank, kein
Keycloak-Client, keine Capability, kein Eintrag im Capability-Katalog. Sie lesen Markdown und sonst
nichts. Entsprechend ist GM-7 unberührt — hier wird nichts entschieden und nichts freigegeben.
Das beantwortet OF-13 nicht. Die Zeile „Second Brain" (Quellenablage) unter „Externe
Abhängigkeiten" weiter unten bleibt unverändert offen. Dort geht es um die Ablage klinischer
Evidenz hinter der Evidenzkennzeichnung (Epic F5 Research, nicht im Schnitt) — Fachinhalt, der in
Empfehlungen einfließt. Hier geht es um die Engineering-Dokumentation dieses Repos. Gleicher
Name, andere Sache; wer beides verwechselt, hält eine offene fachliche Frage für erledigt.
Eigene, isolierte Instanz — keine Föderation. Sie ist nicht die zentrale Second-Brain-Instanz
des Nutzers (C:\dev\secondbrain gegen C:\brain), kennt deren Vault nicht und hat auf ihn keinerlei
Zugriff. brainversum kann zwei Instanzen zusammenschalten (node/gateway, brainversum-ADR-0014
bis -0017); hier läuft der Ein-Prozess-Spezialfall. Das Zusammenschalten ist ein eigener, bewusst
noch nicht gegangener Schritt — vorbereitet ist es (Ports von außen erreichbar, Quelle als
eigenständiger Träger geführt), gebaut ist es nicht.
Zwei benannte Abweichungen, beide in ../../brainversum/README.md
begründet: das Image lässt torch/sentence-transformers weg (318 MB statt 1,36 GB; Suche ist damit
FTS5 statt hybrid — der von brainversum selbst vorgesehene Rückfall), und die zwei Ports binden auf
0.0.0.0 statt wie alles andere hier auf 127.0.0.1, weil der Zugriff von außerhalb der VM der
Zweck ist. brainversum bringt keine Authentifizierung mit; es liegen dort ausschließlich
Engineering-Dokumente und keine Patientendaten.
GG-DEVOPS-0003 (nativ für jeden nicht-lokalen Einsatz) greift hier nicht — das ist keine
Ausnahme wie beim Process-Hub-Cockpit, sondern Nicht-Anwendbarkeit: brainversum ist Python, es gibt
kein JVM-Image, das zu ersetzen wäre. Der Fußabdruck ist mit ~30–60 MiB je Prozess ohnehin die
Größenordnung, auf die die Regel zielt.
Betriebene Zwirn-Docker-Services (Zwirn-ADR-0006)
Fertige Images aus dem Zwirn-Repo. Keine Java-Klasse überquert einen Classpath — der Container ist
die Grenze, konsumiert wird nur über das Netz. Jeder bekommt eine eigene Datenbank; eine über
Produkte hinweg gepoolte Instanz ist ausdrücklich ausgeschlossen (tenantKey ist nur innerhalb eines
Produkts eindeutig). Warum sie hier stehen und was sie kosten:
../../agentic-engineering/backlog/audit-feedback-processhub-integration.md
(Audit/Feedback/Process-Hub),
../../agentic-engineering/backlog/testmanagement-integration.md
(Testmanagement).
| Baustein | Port | Zweck |
|---|---|---|
zwirn-audit-service |
8122 | Protokoll der drei fachlich bedeutsamen Übergänge: Empfehlungen erzeugt, Übersteuerung (GM-7.2), Freigabe erteilt. Frontend: @zwirn/audit |
tuxametrics-audit-redis |
6380 | Der Ingest-Weg, nicht ein Cache: der Audit-Service hat keinen schreibenden REST-Endpunkt, er liest den Redis-Stream events |
tuxametrics-audit-db |
5521 | Eigene DB des Audit-Service. Enthält nur Schlüssel und Zählungen — keine Messwerte, kein Patientenschlüssel, keine Freitext-Begründung |
zwirn-autoimprove-service |
8123 | Claim-basierte Karten-Pipeline über Bugs/Ideen/Aufgaben (NEU → … → ABGENOMMEN), mit AGENT-Actor und gestaffelten menschlichen Freigaben. Registriert 16 eigene autoimprove.*-Capabilities. Frontend: @zwirn/autoimprove (ADR-0007) |
tuxametrics-autoimprove-db |
5522 | Eigene DB des Autoimprove-Service. Port und Slot geerbt vom abgeschalteten Feedback-Service — die Volumes sind nicht übernommen (anderes Schema), Altdaten werden nicht migriert |
zwirn-testmanagement-service |
8127 | Produktneutraler Katalog (TestGroup→TestSubgroup→TestCase) plus TestRun-Protokoll für den fachlichen Testfallkatalog. Kein eigenes Frontend-Paket — Seiten liegen direkt in tuxametrics-ui/src/domains/testfaelle |
tuxametrics-testmanagement-db |
5527 | Eigene DB des Testmanagement-Service |
Nicht mehr betrieben: zwirn-feedback-service. Bis 2026-08-13 hing er auf genau den zwei Ports
oben; seit ADR-0007 ist er
abgeschaltet, samt @zwirn/feedback, html2canvas und dem Melde-Button in der TopNav.
Der Grund ist kein Mangel des Feedback-Service. Zwirn bietet beide Bausteine unabhängig an — den
leichtgewichtigen Rückkanal (OPEN → IN_PROGRESS → RESOLVED) und die claim-basierte Pipeline
(NEU → BEREIT_ZUR_ANALYSE → … → ABGENOMMEN). Für ein Produkt ist die Wahl ein Entweder-oder:
beide gleichzeitig zu betreiben hieße, zwei Rückkanäle mit zwei Zustandsmodellen und zwei Oberflächen
für dieselbe Sache zu haben. tuxametrics hat die Pipeline gewählt; das ist eine Produktentscheidung
und sagt über Zwirn nichts.
Damit ist auch die Frage von 2026-08-09 („erst Feedback sammeln, dann entscheiden, ob es eine zweite
Stufe braucht") beantwortet — mit ja, aber über den kanonischen Service statt über einen Eigenbau.
Das am 2026-08-13 dafür gebaute Modul tuxametrics-feedback-process (ADR-0006, Port 8128, eigene
Engine-DB) ist am Tag darauf ersatzlos entfallen; es beruhte auf einem Recherchefehler, den
ADR-0007 benennt.
Der erste AGENT-Actor des Produkts entsteht dabei — Keycloak-Client
tuxametrics-autoimprove-agent, AGENT-Identity in der VID (boot/AgentIdentitySeeder), drei
autoimprove.*-Grants. Es gibt keinen Betreiber dieser Rolle: kein Scheduler, kein Bot. Die
Karten laufen bis BEREIT_ZUR_ANALYSE und bleiben dort sichtbar stehen, solange niemand claimt.
Und der erste eigene Service-Client: tuxametrics-autoimprove-service (user_key
svc-tuxametrics-autoimprove, tenant_key nur ["platform"]) statt des geteilten
tuxametrics-services. Damit sind es drei Keycloak-Service-Accounts statt einem geteilten für alles —
und ein zweiter Bootstrap-Grant auf platform.capability.create in
boot/CapabilityRegistrar der Authority. Präzedenzfall ist DOT, das denselben Schnitt gewählt hat
(C:\dev\dl-controlling\dot, ADR-0071, „Dedizierter Keycloak-Client").
Ebenfalls aus dieser Adoption entstanden, weil @zwirn/autoimprove es voraussetzt:
GET /api/platform/v1/me/capabilities in der Authority (web/MeResource) — die Selbstauskunft
„was darf ich hier?", an der jede handelnde Schaltfläche der Zwirn-Frontend-Pakete hängt. Sie fehlte
bis dahin; ohne sie wäre das Board für einen berechtigten Menschen stumm bedienungslos gewesen.
Ein Service, acht Domänen — und warum
Das Fachmaterial schneidet acht Domänen (regelwerk, patientenakte, intake, auswertung,
evidenz, therapieplan, bericht, governance). Der Gold Path führt durch sechs davon, und zwar
in einem Durchlauf: eine Auswertung liest Regelwerk und Intake, schreibt Findings, daraus
entstehen Empfehlungen, daraus eine Freigabe, daraus ein Bericht.
Acht Services hätten für diesen einen Durchlauf sieben Netzwerkgrenzen bedeutet — bei einem
Prototyp, dessen Zweck es ist, den Durchlauf zu zeigen. Der Domänenschnitt bleibt als Paketstruktur
und Dokumentation erhalten (domain-map.md); die erste echte Trennung von
Datenhoheit ist der richtige Zeitpunkt für eigene Services, nicht früher.
Am 2026-08-26 ist genau dieser Zeitpunkt einmal eingetreten, und das Argument oben trägt dort
nicht: tuxametrics-substanzstammdaten-service liegt nicht auf dem Durchlauf (er wird
nachgeschlagen, nicht durchlaufen), ist nicht patientenbezogen, nicht mandantengebunden und
soll perspektivisch durch eine externe Quelle ersetzt werden. Er ist damit kein neunter Schnitt
derselben Domäne, sondern die erste echte Datenhoheitsgrenze dieses Repos
(ADR-0012 §1). Für die acht Fachdomänen des
Gold Path bleibt die Aussage oben unverändert gültig.
Externe Abhängigkeiten
| Abhängigkeit | Status |
|---|---|
| Autorisierungs-Authority (Capability-Check) | Entschieden und gebaut (2026-08-10): eigen — tuxametrics-platform-service, Port 8125 (siehe oben). ADR-0005 |
| IdP | Entschieden und gebaut (2026-08-10): Keycloak, Realm digital-labs, Port 8180 (siehe oben) |
| „Second Brain" (Quellenablage) | Vollständig unbeschrieben (OF-13). Epic F5 Research ist nicht im Schnitt; die Evidenzkennzeichnung bleibt, die Quellenablage nicht. Unverändert offen, auch seit 2026-08-26 — seither läuft zwar eine betriebene Brainversum-Quelle, die indexiert aber die Engineering-Doku dieses Repos, nicht klinische Evidenz. Gleicher Name, andere Sache |
| Arzneimitteldatenbank (Handelsname → Wirkstoff) | Präzisiert seit 2026-08-26, nicht erledigt (ADR-0012). Eine offizielle Datenbank ist weiterhin nicht angebunden, und das Fachmaterial hat weiterhin keine Quelle (OF-07). Was es jetzt gibt, ist ein eigener, extern belegter Startkatalog (tuxametrics-substanzstammdaten-service, 11 Wirkstoffe / 14 Handelsnamen aus Gelbe Liste und NIH ODS) — also die Fähigkeit Handelsname → Wirkstoff. Die Interaktionsprüfung bleibt trotzdem draußen: sie bräuchte zusätzlich einen Interaktionskatalog (Wirkstoff × Mikronährstoff), und den gibt es nicht |
Laborschnittstelle (FACH-026) |
Vollständig unbeschrieben (OF-65). Erfassungsart.IMPORTIERT bleibt ungenutzt |
Process-Hub-Aggregator (/api/process-hub/v1/tenants) |
Existiert nirgends — weder in Zwirn noch hier. Deshalb sind Prozessliste und Aufgabenliste aus @zwirn/bpmn nicht gemountet; nur das Cockpit ist verdrahtet. Seit 2026-08-14 kostet das nichts mehr: das einzige Modul dieses Produkts, das eine Aufgabenliste gebraucht hätte, ist mit ADR-0007 entfallen. Der Punkt bleibt offen, ist aber wieder rein theoretisch |
Frontend: Slices plus App-Gerüst
tuxametrics-ui enthält die Domain-Slices (Model/Api/Components/Pages) nach dem Muster aus
zwirn/samples/sample-frontend-react und das App-Gerüst darum herum: Vite, Router, Tailwind.
Layout/Nav (AppLayout/TopNav/Sidebar) sind seit 2026-08-13 produktlokal
(src/shell/, src/nav/navConfig.ts) — Muster aus den Schwesterprodukten eimr/evenews übernommen:
eine einzige, immer sichtbare Sidebar statt Icon-Rail plus separatem Untermenü. @zwirn/web bleibt
nur noch für Auth (useAuth, TokenSync, createOidcConfig) und Theme (useTheme) sowie das
generische cn-Utility im Einsatz. Verifiziert per tsc --noEmit.
Dazu drei Zwirn-Feature-Pakete als file:-Dependency — jedes ist ein eigenes npm-Paket wegen seines
Dependency-Fußabdrucks, nicht aus Ordnungsliebe (Zwirn-ADR-0009/0010/0012):
| Paket | Zusätzliche Last | Wo eingehängt |
|---|---|---|
@zwirn/audit |
keine | Sidebar-Sektion „Protokoll" (Gruppe „Technische Daten") → audit/system-log |
@zwirn/autoimprove |
keine | Sidebar-Sektion „Autoimprove" (Gruppe „Technische Daten") → autoimprove/dashboard, …/board, …/waiting, …/history, …/modules. Ersetzt seit 2026-08-14 @zwirn/feedback (html2canvas). Der Melde-Knopf hängt weiter auf jeder Seite (shell/TopNav.tsx), kommt aber nicht aus dem Paket: es exportiert keinen. Produktlokaler Nachbau in src/domains/autoimprove/, wie in DOT (ADR-0007 §6) — ohne automatischen Screenshot, dafür mit Einfügen/Hochladen |
@zwirn/bpmn |
@xyflow/react |
Sidebar-Sektion „Prozesse" (Gruppe „Technische Daten") → process-hub/cockpit. Lazy geladen, damit kein Patienten-Screen @xyflow/react mitzieht |
Alle drei stehen zusätzlich in zwirn-dedupe.ts — dieselbe Symlink-Falle wie bei @zwirn/web
(zwei Instanzen einer Bibliothek mit Modul-State reißen Auth bzw. Diagramm-Context auseinander).
Die IdP-Frage ist seit 2026-08-10 beantwortet. main.tsx bindet jetzt AuthShell, und die
entscheidet: ein gebautes Artefakt nimmt immer OIDC (AuthProvider + createOidcConfig aus
@zwirn/web, Realm digital-labs, Client tuxametrics-ui). Der DevAuthProvider bleibt daneben
stehen — aber mit veränderter Bedeutung: er war der Ersatz für eine offene Entscheidung, heute ist er
nur noch die Abkürzung für einen Dev-Loop ohne laufende Infrastruktur.
| Befehl | Auth-Weg | Braucht Docker? |
|---|---|---|
npm run dev |
dev/dev-auth-stub.mjs — kein OIDC, kein Realm, jeder Capability-Check allowed: true |
nein |
npm run dev:oidc |
echter Keycloak (/realms-Proxy) + echte Authority auf 8125 |
ja |
npm run build |
immer OIDC | — |
Dass der Stub im gebauten Artefakt nicht existiert, ist keine Konvention, sondern die Bedingung aus
GG-ARCH-SERVICES-0005.5. Deshalb hängt der Default an import.meta.env.PROD und nicht an einer
Variable, die jemand vergessen kann.
Frontend-Module für das Claim-Board
Für CLAIMS.md ist ein Modul sonst eine Zeile aus den
Tabellen oben — also ein Wurzelverzeichnis. Für tuxametrics-ui reicht das nicht: dieses eine
Verzeichnis trägt acht Domain-Slices und das App-Gerüst; „ein Modul = ein Wurzelverzeichnis"
hieße dort „das ganze Frontend ist ein Modul". Am 2026-08-26 kollidierte deshalb shell/TopNav.tsx
(Marken-Icon) mit components/KpiCard.tsx und routes/HomeRoute.tsx (Kacheln der Startseite) —
zwei Arbeiten, die sich fachlich nie berührt hätten (CLAIMS.md § Historie).
Ein Frontend-Modul ist deshalb ein Domain-Slice oder einer der geteilten src/-Bereiche:
| Modulname im Board | Deckt ab |
|---|---|
tuxametrics-ui/<slice> |
src/domains/<slice>/** — je ein Ordner unter src/domains/ |
tuxametrics-ui/<bereich> |
src/<bereich>/** — je ein direkter Ordner unter src/ außer domains |
tuxametrics-ui/app-shell |
alles Übrige: src/App.tsx, src/main.tsx, src/index.css, src/index.ts, package.json, vite.config.ts, index.html, tailwind.config.js |
Diese Liste ist mechanisch aus dem Dateisystem abgeleitet und hier nur zur Orientierung
dokumentiert — nicht vorgeschrieben. Der PreToolUse-Guard liest sie zur Laufzeit
(.claude/hooks/lib.mjs, discoverFrontendModules) und löst einen konkreten Pfad ohne Umweg über
eine Liste auf. Ein neuer Ordner unter src/domains/ ist damit sofort ein eigenes Modul — ohne
Codeänderung und ohne Nachtrag hier. Eine handgepflegte Liste würde genau dann rotten, wenn ein
Slice neu ist und Kollisionen am wahrscheinlichsten sind.
Der Stand vom 2026-08-26, rein als Momentaufnahme: Slices auswertung, autoimprove, bericht,
patient, regelwerk, systemsteckbrief, testfaelle, therapieplan; geteilte Bereiche api,
auth, components, lib, nav, routes, shell. Wer den aktuellen Stand braucht, liest nicht
diesen Absatz, sondern ls tuxametrics-ui/src und ls tuxametrics-ui/src/domains.
Zwei Punkte, die man kennen muss:
app-shellist bewusst ein Modul und ausdrücklich nicht „claim-frei". GenauApp.tsxundnav/navConfig.tswaren am 2026-08-26 Teil der Kollisionskette; das sind die Dateien, die jeder Slice mitbenutzt. Sie für claim-frei zu erklären hieße zu behaupten, dort kollidiere nichts.- Eine Altzeile
tuxametrics-uisperrt weiterhin das ganze Frontend. Ein Claim auf das Obermodul deckt seine Untermodule mit ab — umgekehrt nicht:tuxametrics-ui/patientsperrttuxametrics-ui/shellnicht, sonst wäre die feinere Auflösung wirkungslos.
Die Backend-Services sind davon unberührt: sie sind je ein eigenes Wurzelverzeichnis und damit bereits richtig geschnitten. Ein Modul bleibt dort das ganze Verzeichnis.