| 15-modul-berechtigungen-gruppen-user-grants |
07 |
ui |
| nextjs |
| next-intl |
| react |
| admin |
| module-grants |
| groups |
|
| phase |
plan |
provides |
| 15-modul-berechtigungen-gruppen-user-grants |
03 |
ModuleGrantsService/ModuleGrantsController (grant/revoke/getMatrix/getUserAccess), GET /modules/catalog Statusflags |
|
| phase |
plan |
provides |
| 15-modul-berechtigungen-gruppen-user-grants |
06 |
/admin/groups Admin-UI, alle i18n-Schluessel der gesamten Phase 15 (inkl. adminModules.grants.*/activationDialog.*, admin.users.grants.*, admin.groups.grants.matrixCheckboxLabel) |
|
|
| Freigabe-Matrix Module x Gruppen unter /admin/modules/grants (D-15, PERM-03) -- sticky Kopf/Spalte, Kategorie-Gruppierung, Suchfeld, sofortiges optimistisches Toggle mit Rollback |
| ActivateModuleDialog mit drei Aktionen (Abbrechen / Spaeter konfigurieren / Sofort freigeben) beim Aktivieren eines Moduls (D-10, D-13) |
| UserAccessModal im Benutzer-Detail: read-only Gruppenmitgliedschaften + Modul-Zugriffstabelle mit geerbten Gruppen und Direkt-Toggle (D-16, PERM-03) |
|
|
| tokens |
tasks |
commits |
| 12861 |
3 |
3 |
|
| added |
patterns |
|
|
| aria-label des Grant-Checkboxes beschreibt die vom Klick ausgeloeste Aktion (freigeben/entziehen), nicht den aktuellen Zustand -- granted-Parameter der matrixCheckboxLabel/directCheckboxLabel-ICU-select-Schluessel erhaelt !isGranted, nicht isGranted |
| UserAccessModal leitet die Gruppenmitgliedschafts-Chipliste ausschliesslich aus der dedupliziertem Vereinigung aller viaGroups-Namen von GET /module-grants/users/:userId ab -- kein zweiter Endpoint fuer die reine Mitgliedschaftsliste, exakt wie der Plan-key_link es vorgibt ('geerbte und direkte Rechte kommen aus einer Antwort') |
| ActivateModuleDialog aktualisiert den Aktivierungs-Zustand des Aufrufers bereits nach dem erfolgreichen activate-Call, bevor der optionale module-grants-Call laeuft -- das Modul ist ab diesem Zeitpunkt echt aktiv, unabhaengig vom Ausgang des zweiten Calls |
|
|
| created |
modified |
| apps/web/src/app/(portal)/admin/modules/grants/page.tsx |
| apps/web/src/app/(portal)/admin/modules/grants/grants-matrix.test.tsx |
| apps/web/src/app/(portal)/admin/modules/components/ActivateModuleDialog.tsx |
| apps/web/src/app/(portal)/admin/users/components/UserAccessModal.tsx |
| apps/web/src/app/(portal)/admin/users/user-access-modal.test.tsx |
|
| apps/web/src/app/(portal)/admin/modules/page.tsx |
| apps/web/src/app/(portal)/admin/users/page.tsx |
|
|
| Suchfeld der Matrix filtert Modul- und Gruppennamen unabhaengig voneinander (zwei getrennte .filter()-Aufrufe auf dieselbe searchLower-Variable) statt einer kombinierten Sichtbarkeitsregel -- einfachste Interpretation von 'filtert clientseitig sowohl Modul- als auch Gruppennamen', kein Praezedenzfall im Bestandscode fuer eine 2D-Matrix-Suche |
| granted-Interpolationsparameter der ICU-select-Aria-Label-Schluessel wird als String(!isGranted)/String(!row.direct) uebergeben -- next-intl/TypeScript akzeptiert fuer Message-Params nur string/number/Date, kein boolean; und der Parameterwert beschreibt bewusst die bevorstehende Aktion, nicht den aktuellen Haekchen-Zustand (den vermittelt bereits checked/aria-checked) |
| ActivateModuleDialog fuehrt beide Aufrufe nicht optimistisch, sondern sequenziell und wartend aus -- da 'Sofort freigeben' zwei echte HTTP-Calls in fester Reihenfolge ist (activate dann grant, laut Plan bewusst kein kombinierter Endpoint), waere ein optimistisches Vorab-Setzen beider Zustaende vor Bestaetigung irrefuehrend; onSuccess wird erst nach dem ersten erfolgreichen Call aufgerufen, weil das Modul ab da unabhaengig vom zweiten Call wirklich aktiv ist |
|
|
| id |
description |
requirement |
verification |
human_judgment |
| D1 |
Freigabe-Matrix Module x Gruppen unter /admin/modules/grants: sticky erste Spalte/Kopfzeile, Kategorie-Gruppierung, Suchfeld, sofortiges optimistisches Toggle mit Rollback + sichtbarer Fehlermeldung bei Fehlschlag, aria-label je Checkbox, Admin-Bypass-Fussnote, leerer Zustand ohne aktive Module |
PERM-03 |
| kind |
ref |
status |
| unit |
apps/web/src/app/(portal)/admin/modules/grants/grants-matrix.test.tsx (describe 'AdminModuleGrantsPage': 5 Tests -- befuellte Matrix, leerer Zustand, Rollback bei Fehler, Suchfilter, aria-label je Checkbox) |
pass |
|
| kind |
ref |
status |
| other |
grep-Nachweise aus Task-1-acceptance_criteria (sticky left-0/top-0, truncate, title=, aria-label, adminNote, grantsLink) + pnpm --filter @tessera/web run build |
pass |
|
|
false |
|
| id |
description |
requirement |
verification |
human_judgment |
| D2 |
ActivateModuleDialog: drei Aktionen (Abbrechen/Spaeter konfigurieren/Sofort freigeben), Sofort-freigeben deaktiviert mit Hinweistext ohne markierte Standardgruppe (D-13), Aufrufreihenfolge activate->module-grants bei Sofort freigeben |
PERM-03 |
| kind |
ref |
status |
| unit |
apps/web/src/app/(portal)/admin/modules/grants/grants-matrix.test.tsx (describe 'ActivateModuleDialog': 3 Tests -- alle drei Buttons, Deaktivierung + Hinweistext ohne Standardgruppe, Aufrufreihenfolge) |
pass |
|
| kind |
ref |
status |
| other |
grep-Nachweise aus Task-2-acceptance_criteria (max-w-sm, noDefaultGroupHint, disabled, break-words, ActivateModuleDialog in page.tsx) + pnpm --filter @tessera/web run build |
pass |
|
|
false |
|
| id |
description |
requirement |
verification |
human_judgment |
| D3 |
UserAccessModal im Benutzer-Detail: read-only Gruppenmitgliedschafts-Chipliste (kein zweites Bearbeitungsziel, D-16), Modul-Zugriffstabelle mit geerbten Gruppen-Chips oder Gedankenstrich, Direkt-Checkbox mit optimistischem Toggle + Rollback, Hinweistext ohne aktive Module, aria-label je Checkbox |
PERM-03 |
| kind |
ref |
status |
| unit |
apps/web/src/app/(portal)/admin/users/user-access-modal.test.tsx (5 Tests -- Chip-Liste + Leerzustand, Modultabelle mit geerbtem/nicht-geerbtem Modul, Rollback bei Fehler, Hinweistext ohne aktive Module, aria-label je Checkbox) |
pass |
|
| kind |
ref |
status |
| other |
grep-Nachweise aus Task-3-acceptance_criteria (max-w-2xl, noActiveModules, directCheckboxLabel, module-grants/users, detailsButton) + pnpm --filter @tessera/web run build |
pass |
|
|
false |
|
| id |
description |
verification |
human_judgment |
rationale |
| D4 |
Vollstaendiges manuelles Durchklicken im Browser aus dem Plan-<verification>-Block: Freigabe in der Matrix setzen/entziehen und mit Testbenutzer gegenpruefen, Modul aktivieren ueber beide Dialogwege, Direkt-Grant neben bestehendem Gruppen-Grant im Benutzer-Detail setzen, Fehlerfall bei gestoppter API, lange Gruppen-/Modulnamen |
|
true |
Diese Session hatte kein Browser-/Playwright-Tool zur Verfuegung (nur Read/Write/Edit/Bash/Skill) -- identisch zur Vorbedingung in 15-06. Der interaktive Durchlauf aus dem Plan-<verification>-Block konnte nicht ausgefuehrt werden. Abgedeckt ist stattdessen: voller Vitest-Lauf (175/175 gruen, davon 13 neue Tests fuer diesen Plan), fehlerfreier Produktions-Build inkl. Next.js-Typecheck, sowie alle grep-basierten acceptance_criteria aus allen drei Tasks. In WINDOWS.md als unrun-verify vermerkt. |
|
|
ca. 30min |
2026-08-04 |
complete |