Files
tessera-ctl/.planning/quick/261002-icv-modul-freigabe-mit-stufe-verwalten-modul/261002-icv-SUMMARY.md
T
schalli 7188733f70
Tessera CI/CD / Lint & Type Check (push) Successful in 56s
Tessera CI/CD / Tests (push) Successful in 2m3s
Tessera CI/CD / Desktop-Pakete bauen (push) Successful in 21s
Tessera CI/CD / Build & Publish Images (push) Successful in 3m28s
docs(quick-261002-icv): Freigabestufe Verwalten
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 13:42:22 +02:00

12 KiB
Raw Blame History

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
berechtigungen
freigabestufe
module-guard
prisma
nestjs
nextjs
complete 2026-10-02 3 b94d267584 eaf2c4574a
tasks commits
3 3
ModuleGrant.level (USE/MANAGE), Bestand = USE
ModuleAccessService.getModuleAccessLevels als einzige Auflösung für Zugriff und Stufe
@ModuleManage(slug) am ModuleGuard
GET /modules/active liefert canManage je Modul
Web-Hook useCanManageModule(slug)
kantine-datev
handelsware-datev
proxmox
dkv-fleet
admin-freigaben
created modified
apps/api/prisma/migrations/20261002140000_module_grant_level/migration.sql
apps/api/src/groups/dto/create-module-grant.dto.spec.ts
apps/api/src/module-registry/module-manage-handlers.spec.ts
apps/web/src/lib/use-module-capability.ts
apps/api/prisma/schema.prisma
apps/api/src/module-registry/module-access.service.ts
apps/api/src/module-registry/module.guard.ts
apps/api/src/groups/module-grants.service.ts
apps/api/src/groups/dto/create-module-grant.dto.ts
apps/api/src/kantine-datev/kantine-datev.controller.ts
apps/api/src/handelsware-datev/handelsware-datev.controller.ts
apps/api/src/proxmox/proxmox.controller.ts
apps/api/src/dkv/dkv.controller.ts
apps/web/src/lib/module-access-actions.ts
apps/web/src/components/modules/module-access-gate.tsx
apps/web/src/app/(portal)/admin/modules/grants/page.tsx
apps/web/src/app/(portal)/admin/users/components/UserAccessModal.tsx
Stufe wird ausschließlich serverseitig aus ModuleGrant-Zeilen aufgelöst; MANAGE gewinnt bei mehreren Wegen.
Wiederholter Klick auf eine Matrix-Zelle (POST ohne level) ändert die Stufe nie.
DKV-Fleet wird als Ganzes Verwalten-Stufe, Benutzen-Stufe bekommt keinen API-Zugriff (wie bisher).

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.getModuleAccessLevels ist 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 denselben forTenant-Klienten. getAccessibleModuleIds ist nur noch die Schlüsselmenge (Signatur unverändert), findAccessibleModules liefert canManage.
  • ModuleGuard liest MODULE_MANAGE_KEY, nutzt pro Request request.moduleAccessLevels (Klassen-@UseModule plus Handler-@ModuleManage fragen den Dienst nur einmal) und wirft bei Stufe USE Module '<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 (Logzeile Grant-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-fleet für den Mandanten verlangt (die Webseite verlangte sie schon). Ein Administrator ohne Aktivierung wird jetzt von der API ebenfalls abgewiesen.
  • ModuleAccessGate zeigt 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 betroffenen admin-Tests erneut grün, 7 Dateien, 96 Tests).
  • tsc: tsc --noEmit in api und web ohne Fehler.
  • Biome: biome lint auf allen berührten TS/TSX-Dateien ohne neue Meldungen. Zwei bereits vorhandene Warnungen bleiben bestehen und stammen nicht aus diesem Plan (noAssignInExpressions in migration-sql.spec.ts, noArrayIndexKey in grants/page.tsx).
  • Lokaler Stand: docker compose up -d --build api web erfolgreich; api, web und db laufen; Log meldet Nest 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.tsx blendete 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)

  • a222711 feat(module-grants): Freigabestufe Verwalten – Datenbank, Zugriffsprüfung und Kantinen-Einstellungen
  • c2ebc8d feat(module-grants): Proxmox, Handelsware und DKV mit Freigabestufe Verwalten
  • eaf2c45 feat(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.ts vorhanden.
  • 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.