--- phase: 15-modul-berechtigungen-gruppen-user-grants kind: uat-nachtrag date: 2026-09-07 windows_addressed: [1, 2, 3] windows_opened: [10] result: 2 von 3 bestanden, 1 mit Befund --- # Phase 15 — Browser-Gegenproben, nachgeholt am 2026-09-07 Die drei Browser-Durchläufe aus den Plänen 15-06, 15-07 und 15-08 waren seit dem 2026-08-04 offen, weil in den damaligen Ausführungssitzungen kein Browser-Tool verfügbar war (WINDOWS.md #1, #2, #3). Sie wurden jetzt nachgeholt. **Aufbau:** frisch gebaute Images aus `main` (`79015dd`), lokaler Docker-Stack, leere Datenbank, echter Chrome über Playwright. Testdaten über die Oberfläche angelegt: Modul im Marktplatz aktiviert, zwei USER-Konten (`nutzer1`, `nutzer2`) im selben Mandanten, Gruppen und Freigaben über die Administrationsseiten. ## WINDOWS #1 — Gruppenverwaltung (15-06) — BESTANDEN | Schritt aus dem Plan | Beobachtung | |---|---| | Gruppe anlegen | „Vertrieb" erscheint in der Liste, Spalte AD-Bindung „Manuell", 0 Mitglieder | | Umbenennen | Auf „Vertrieb Innendienst" geändert, Liste zieht nach | | Standardmarkierung setzen | Markierung wandert exklusiv: „Alle Benutzer" wechselt auf „Als Standardgruppe festlegen", die neue Gruppe trägt „Standardgruppe" | | Standardmarkierung wieder abschalten | Durch Setzen bei „Alle Benutzer" zurückgewandert | | Mitglied hinzufügen | „Nutzer Eins" erscheint mit Herkunfts-Badge „Manuell"; seine Auswahl-Checkbox ist danach gesperrt, ein Doppel-Hinzufügen also nicht möglich | | Mitglied entfernen | Liste wieder leer, Checkbox wieder frei | | Löschdialog mit gefüllter Gruppe | „Diese Gruppe hat 1 Mitglieder und 1 Modul-Freigaben." — beide Zahlen konkret genannt (D-17) | | Löschvorgang bei gestoppter API | Sichtbare deutsche Klartextmeldung „Gruppe konnte nicht gelöscht werden. Bitte erneut versuchen.", Löschen-Knopf danach gesperrt, Gruppe bleibt in der Liste | **Nicht mehr prüfbar, weil bewusst geändert:** Der Plan verlangte „an eine AD-Gruppe binden und Bindung lösen" sowie die AD-Suche bei gestoppter API. Beides gibt es an dieser Stelle nicht mehr. Phase 16 hat den Anlegen-Dialog umgebaut: er trägt jetzt den Hinweis „AD-Gruppen werden im LDAP-Bereich importiert, nicht hier angelegt." samt Link dorthin. Die Prüfpunkte sind damit gegenstandslos, nicht übersprungen. **Kleiner Sprachbefund:** Der Löschdialog schreibt „1 Mitglieder" statt „1 Mitglied" — Plural auch bei Eins. ## WINDOWS #2 — Freigaben-Matrix und Direkt-Grants (15-07) — BESTANDEN | Schritt aus dem Plan | Beobachtung | |---|---| | Freigabe in der Matrix setzen | Checkbox für „Vertrieb Innendienst" gesetzt, Beschriftung wechselt von „freigeben" auf „entziehen" | | Freigabe wieder entziehen und Wirkung gegenprüfen | Entzug für „Alle Benutzer" führte dazu, dass `nutzer2` den Zugriff sofort verlor — belegt über alle vier Ebenen unter #3 | | Aktivierungsdialog, Weg „Sofort freigeben" | Cert Manager aktiviert; Grant an die Standardgruppe „Alle Benutzer" entstand (D-10) | | Aktivierungsdialog, Weg „Später konfigurieren" | DKV-Rechnung aktiviert; **kein** Grant entstanden (0 Freigaben in der Datenbank) | | Direkt-Grant neben Gruppen-Grant | Im Benutzer-Detail von `nutzer1` zeigt die Spalte „Über Gruppe(n)" beide freigebenden Gruppen an, während die Spalte „Direkt" unabhängig davon gesetzt werden kann | | Matrix-Zelle bei gestoppter API | Fehlermeldung erscheint **und** die Checkbox springt in ihren alten Zustand zurück; die Datenbank zeigt danach unveränderte Freigaben — kein optimistischer Zustand überlebt den fehlgeschlagenen Request. Beleg: `uat-2026-09-07/w2-matrix-rollback-api-aus.png` | | Direkt-Kästchen bei gestoppter API | Fehlermeldung im Dialog, Grant unverändert in der Datenbank | | Sehr langer Gruppenname | Kopfzeile schneidet mit Ellipse ab („Abteilung Zentraler Einkauf und Vergabemanagement…"), Spaltenbreiten bleiben, die Seite scrollt nicht horizontal. Beleg: `uat-2026-09-07/w2-matrix-lange-namen.png` | **Befunde ohne Blockerwirkung:** - Die Fehlermeldung bei gestoppter API lautet in Matrix und Benutzer-Detail roh „500: Internal Server Error". Der Löschdialog der Gruppenseite kann es besser (deutscher Klartext) — die Behandlung ist also uneinheitlich. - Wird eine Matrix-Seite bei bereits gestoppter API frisch geladen, meldet sie dem Administrator „Zugriff verweigert" statt „Server nicht erreichbar". Das ist eine irreführende Diagnose: der Administrator vermutet ein Rechteproblem statt eines Serverausfalls. - Der Aktivierungsdialog duzt („möchtest du die Freigaben separat konfigurieren?"), während die übrige Oberfläche siezt. - Das Deaktivieren eines Moduls entfernt seine Freigaben nicht. Beim Wiederaktivieren sind die alten Freigaben sofort wieder wirksam. Das wirkt gewollt, ist aber nirgends festgehalten. ## WINDOWS #3 — Sperrung ohne Freigabe über alle vier Ebenen (15-08) — DURCHGEFÜHRT, MIT BEFUND Geprüft mit `nutzer2` (Rolle USER, Freigabe für Ausschreibungs-Radar entzogen) gegen `nutzer1` (Freigabe über Gruppe) und `admin`. | Ebene | Ergebnis | |---|---| | 1. Sidebar | Kategorie „procurement" fehlt für `nutzer2` vollständig; nur „security tools" (Cert Manager, dort freigegeben) erscheint ✓ | | 2. Direkte URL `/modules/procurement/tender-radar` | 403-Seite „Kein Zugriff auf dieses Modul" mit Handlungsanweisung und Weg zurück ✓ (D-07) | | 3. Marketplace | Karte trägt „Aktiviert" **und** das Sperr-Badge „Kein Zugriff", ist nicht anklickbar; der Klick löst den Toast „Kein Zugriff auf dieses Modul — wende dich an deinen Administrator." aus und navigiert **nicht** ✓ (D-08). Modul wird gekennzeichnet, nicht ausgeblendet | | 4. API | `nutzer2` erhält auf `/modules/tender-radar` und allen geprüften Unterendpunkten (`saved-searches`, `rss-feeds`, `email-config`) durchgehend HTTP 403; `nutzer1` durchgehend 200 ✓ | **Der Nachweis von PERM-04 gelingt damit auf drei von vier Ebenen nicht vollständig — siehe WINDOWS #10.** ### WINDOWS #10 (neu) — der Zugriffs-Guard greift nicht auf modul-eigenen Routen Ebene 2 ist nur für die generische Route abgesichert. Der Guard sitzt in `modules/[category]/[moduleSlug]/page.tsx`. Vier Module haben daneben fest verdrahtete eigene Routen: ``` apps/web/src/app/(portal)/modules/cert-manager/ apps/web/src/app/(portal)/modules/dkv-fleet/ apps/web/src/app/(portal)/modules/domaincheck/ apps/web/src/app/(portal)/modules/tender-radar/ ``` Diese laufen am Guard vorbei. Im Browser als `nutzer2` **ohne** Freigabe gemessen: | Adresse | Ergebnis | |---|---| | `/modules/procurement/tender-radar` | 403-Seite ✓ (generische Route, abgesichert) | | `/modules/tender-radar` | **volle Seite** — Überschrift, Filter, Suchprofil-Formular, Trefferliste, Zahnrad-Link | | `/modules/tender-radar/my-sources` | **volle Seite** — Postfach-Formular, Feed-Formular, Digest-Auswahl, alle Knöpfe bedienbar | | `/modules/dkv-fleet` | **volle Seite** — inklusive Knopf „Jetzt pruefen" und Link zu den Moduleinstellungen | **Es werden keine Daten preisgegeben.** Die API antwortet auf jedem Endpunkt mit 403, die Listen bleiben leer. Der Defekt liegt auf der Anzeigeebene: 1. Der Nutzer sieht eine Seite, die er nicht benutzen darf, statt der 403-Seite. 2. Die Bedienelemente sind anklickbar und laufen ins Leere — genau das, was Plan 17-03 auf der Einstellungsseite des Ausschreibungs-Radars abgeschafft hat. 3. Statt einer verständlichen Meldung erscheinen rohe englische Techniktexte mitten in der deutschen Oberfläche: „Module 'tender-radar' is not accessible for this user", „Failed to fetch tenders", „Failed to fetch saved searches", „Failed to fetch notification preference". Beleg: `uat-2026-09-07/befund-modul-eigene-route-ohne-freigabe.png` **Erwartete Behebung:** Die Zugriffsprüfung gehört in ein gemeinsames Layout über allen Modulrouten (etwa `(portal)/modules/layout.tsx` mit Auflösung des Modul-Slugs aus dem Pfad) statt in die einzelne Seitenkomponente der generischen Route. ## Ergebnis WINDOWS #1 und #2 sind geschlossen. #3 ist als Durchlauf erledigt; der dabei gefundene Defekt ist als #10 eigenständig erfasst und bleibt offen.