12 KiB
phase, plan, quick_id, subsystem, tags, status, completed, commits, plan_head_before, plan_head_after, actuals, requires, provides, affects, key-files, decisions
| phase | plan | quick_id | subsystem | tags | status | completed | commits | plan_head_before | plan_head_after | actuals | requires | provides | affects | key-files | decisions | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| quick-261002-icv | 01 | 261002-icv | module-grants |
|
complete | 2026-10-02 | 3 | b94d267584 |
eaf2c4574a |
|
|
|
|
|
Quick 261002-icv: Modul-Freigabe mit Stufe Benutzen und Verwalten
Jede Modul-Freigabe (Gruppe oder einzelner Benutzer) hat jetzt eine Stufe: Benutzen (USE, Standard und Bestand) oder Verwalten (MANAGE, zusätzlich die eigenen Einstellungen dieses einen Moduls ändern). Die Stufe wird im Backend über den neuen Dekorator @ModuleManage('<slug>') am ModuleGuard erzwungen. Die Weboberfläche erfährt die wirksame Stufe aus GET /modules/active (canManage) und zeigt Einstellungen nur Administratoren und Verwaltern. Administratoren vergeben die Stufe in der Freigaben-Matrix (je Gruppe) und im Benutzer-Detaildialog (je Benutzer).
Was gebaut wurde
Datenbank (Task 1). Migration 20261002140000_module_grant_level (von Hand geschrieben): CREATE TYPE "ModuleGrantLevel" und ADD COLUMN "level" ... NOT NULL DEFAULT 'USE'. Lokal angewendet über die Container-IP; prisma migrate status aktuell, Drift-Prüfung (migrate diff --exit-code) Rückgabewert 0. Die vorhandenen vier Freigaben stehen lokal alle auf USE. Keine neue Tabelle, daher keine Änderung an RLS-Regeln; rls-coverage und rls-access-inventory grün.
Zugriffsauflösung und Wächter (Task 1).
ModuleAccessService.getModuleAccessLevelsist die einzige Auflösung: ADMIN/SUPER_ADMIN bekommen auf jedem aktiven Modul MANAGE ohne Grant-Abfragen; andere Rollen Direkt- plus Gruppen-Grants, MANAGE gewinnt, geschnitten mit aktiven Aktivierungen (MANAGE auf deaktiviertem Modul zählt nicht). Alles über denselbenforTenant-Klienten.getAccessibleModuleIdsist nur noch die Schlüsselmenge (Signatur unverändert),findAccessibleModulesliefertcanManage.ModuleGuardliestMODULE_MANAGE_KEY, nutzt pro Requestrequest.moduleAccessLevels(Klassen-@UseModuleplus Handler-@ModuleManagefragen den Dienst nur einmal) und wirft bei Stufe USEModule '<slug>' requires manage permission. MANAGE gilt nur für das Modul der Route.CreateModuleGrantDto.level(optional,@IsEnum).ModuleGrantsService.grant: ohne Stufe USE; vorhandene Freigabe wird nur bei ausdrücklich anderer Stufe geändert (LogzeileGrant-Stufe geändert … level=…), ein Wiederholungsklick stuft nie herab; P2002-Wettlauf wendet dieselbe Regel an.
Umgestellte Handler (Tasks 1 und 2).
| Controller | Auf @ModuleManage umgestellt |
|---|---|
KantineDatevController |
saveSettings (kantine-datev) |
HandelswareDatevController |
saveSettings (handelsware-datev) |
ProxmoxController |
create, update, remove, poll, test, testDraft (proxmox); list bleibt Benutzen |
DkvController |
ganze Klasse (dkv-fleet), alle 11 früheren @Roles entfernt |
In den vier Controllern steht kein dekoratorseitiges @Roles mehr.
Web (Tasks 1 bis 3). useCanManageModule(slug) (Admins sofort true ohne Abfrage, sonst eine Abfrage von /modules/active, Fehler = false). Kantinenabrechnung, Handelsware, Proxmox-Seite, Proxmox-Einstellungen, ServerCard/ServerForm (Props isAdmin zu canManage) und das Proxmox-Dashboard-Widget (Einstellungs-Link) folgen canManage. Neue Server-Funktion getModuleAccessLevel; checkModuleAccess delegiert. ModuleAccessGate kennt MANAGE_ONLY_MODULE_SLUGS = {'dkv-fleet'}. Matrix und Benutzerdialog haben ein Stufen-Auswahlfeld (optimistisch, Rücksprung bei Fehler); Gruppen, die Verwalten gewähren, sind im Dialog mit „Verwalten“ markiert. Die API liefert dafür level je Matrix-Eintrag sowie directLevel und manageViaGroups je Modulzeile.
Texte, Doku, Changelog. Neue Schlüssel in de.json/en.json (formales „Sie“, echte Umlaute, kein „Mandant“/Tenant in den neuen Formulierungen; per Skript geprüft). docs/anleitung-administration.md (Kapitel 1, 2, 5 mit neuem Abschnitt „Freigabestufen: Benutzen und Verwalten“, Fehlersuche), docs/anleitung-anwender.md, CHANGELOG.md (Unveröffentlicht, Neu).
Bewusst nur für Administratoren
Diese Handler blieben unverändert auf @Roles(ADMIN, SUPER_ADMIN); die Metadaten-Spec module-manage-handlers.spec.ts beweist das:
| Handler | Grund |
|---|---|
TendersController.getSourceConfig |
plattformweiter Singleton der Abrufeinstellungen für die ganze Installation, keine Konfiguration eines einzelnen Moduls je Firma |
TendersController.saveSourceConfig |
wie oben; ändert Abrufintervall und Quelle für alle |
TendersController.pollNow |
stößt den plattformweiten Abruf beim Datenanbieter an (Lastschalter, T-lvg-01) |
TendersController.createRssFeed (Bereich „platform“), removeRssFeed (plattformweiter Zweig) |
prüfen die Rolle inline; plattformweite RSS-Feeds sehen alle Benutzer der Installation. Nicht angefasst |
ModuleRegistryController.activate / deactivate |
Modul-Aktivierung ist Sache der Administratoren (L-01) |
ModuleGrantsController.matrix / userAccess / create / remove |
Freigaben vergeben und Stufe wählen bleibt Administratoren vorbehalten (L-01); sonst könnte sich ein Verwalter selbst Rechte geben (T-icv-01) |
| Benutzer-, Gruppen-, LDAP-, SMTP-, Willkommensmail-, Mandanten-Controller | globale Administration, nicht modulgebunden |
Gemeinsame eigene Module (custom-modules) |
kein Registry-Modul und kein @UseModule; Seitenleisten-Einträge für alle, Rollenprüfung im Dienst |
Geprüft mit grep -rn "Roles(" apps/api/src: cert-manager, domaincheck und reminders haben keinen Administrator-Handler, also nichts umzustellen.
DKV-Verhalten (Änderung)
Vorher trug jeder der 11 DKV-Handler @Roles(ADMIN, SUPER_ADMIN), das Modul war faktisch nur für Administratoren benutzbar, und der Controller hatte kein @UseModule. Jetzt trägt die ganze Klasse @ModuleManage('dkv-fleet'):
- Zugriff haben Administratoren und Benutzer mit Stufe Verwalten.
- Benutzer mit nur Benutzen bekommen weiterhin 403 von der API (nichts wurde aufgeweitet).
- Neu ist, dass der Wächter zusätzlich die Aktivierung von
dkv-fleetfür den Mandanten verlangt (die Webseite verlangte sie schon). Ein Administrator ohne Aktivierung wird jetzt von der API ebenfalls abgewiesen. ModuleAccessGatezeigt Benutzern mit nur Benutzen eine erklärende Zugriffsseite („Dieses Modul steht nur Benutzern zur Verfügung, die es verwalten dürfen …“), sonst den Standardtext.
Tests und Prüfungen (ehrlich)
- API:
pnpm --filter @tessera/api test: 111 Dateien, 1911 Tests, alle grün (vorher in den Teilläufen u. a.rls-coverage,rls-access-inventory,migration-sql). - Web:
pnpm --filter @tessera/web test: 115 Dateien, 1234 Tests, alle grün (Vollauf vor einer reinen Umbenennung unbenutzter Testparameter; danach die betroffenenadmin-Tests erneut grün, 7 Dateien, 96 Tests). - tsc:
tsc --noEmitin api und web ohne Fehler. - Biome:
biome lintauf allen berührten TS/TSX-Dateien ohne neue Meldungen. Zwei bereits vorhandene Warnungen bleiben bestehen und stammen nicht aus diesem Plan (noAssignInExpressionsinmigration-sql.spec.ts,noArrayIndexKeyingrants/page.tsx). - Lokaler Stand:
docker compose up -d --build api weberfolgreich; api, web und db laufen; Log meldetNest application successfully started, kein Migrations- oder Prisma-Fehler. Browserprüfung macht der Orchestrator.
Abweichungen vom Plan
1. [Rule 2 - Konsistenz] Proxmox-Dashboard-Widget auf canManage umgestellt
- Gefunden bei: Task 2
- Problem:
proxmox-widget.tsxblendete den Link „Zu den Einstellungen“ nur für Administratoren ein, obwohl Verwalter die Einstellungsseite jetzt nutzen dürfen. Die Datei stand nicht in der Dateiliste des Plans. - Fix:
useCanManageModule('proxmox')statt Rollenprüfung; bestehender Widget-Test blieb grün. - Commit:
c2ebc8d
2. [Rule 1 - Typfehler] applyToExisting in ModuleGrantsService.grant brauchte den Typ ModuleGrant, damit tsc die Spec akzeptiert. Behoben vor dem Commit von Task 1 (a222711).
Sonst: Plan wie geschrieben ausgeführt. Die Metadaten-Spec liegt wie geplant als eine Datei vor. Beim Handelsware-Test wurde eine Textprüfung (/Ein Administrator muss zuerst/) an den neuen Wortlaut angepasst, ebenso bei der Kantinenabrechnung.
Bekannte Stubs
Keine.
Threat Flags
Keine neuen Angriffsflächen außerhalb des Bedrohungsmodells des Plans. Hinweis zu T-icv-09: Wer für Proxmox „Verwalten“ erhält, darf Serveradressen eintragen (private Ziele per Design); das steht im Kommentar von proxmox-client.service.ts und im Administrationshandbuch.
Commits (nicht gepusht)
a222711feat(module-grants): Freigabestufe Verwalten – Datenbank, Zugriffsprüfung und Kantinen-Einstellungenc2ebc8dfeat(module-grants): Proxmox, Handelsware und DKV mit Freigabestufe Verwalteneaf2c45feat(module-grants): Stufe Verwalten in Freigaben-Matrix und Benutzerdetails, Doku und Changelog
Self-Check: PASSED
- Migration,
module.guard.ts,use-module-capability.ts,module-manage-handlers.spec.ts,create-module-grant.dto.spec.tsvorhanden. - Alle drei Commit-Hashes existieren auf
main(git rev-list --countüber das Ledger: 3). - Keine unbeabsichtigten Löschungen in den Commits.
Browser-Prüfung (Orchestrator, 02.10., lokal, dunkel)
- Testgruppe „Buchhaltung Test“ mit Testbenutzer (USER) per API angelegt; in der Freigaben-Matrix Kantinenabrechnung = Verwalten, Handelsware = Benutzen gesetzt, bleibt nach Neuladen erhalten.
- Als Testbenutzer: Kantine zeigt Reiter Einstellungen, Speichern klappt; Handelsware ohne Einstellungs-Reiter; API: Handelsware-Einstellungen PUT → 403, DKV ohne Freigabe → 403.
- Korrektur: Matrix zeigte Kategorie-Kennungen („accounting“) → jetzt Anzeigenamen (Finanzbuchhaltung, Fuhrpark, …).
- Testbenutzer und Testgruppe wieder gelöscht.