Files
tessera-ctl/.planning/quick/260914-ebg-windows-29-schliessen-rechteausweitung-a/260914-ebg-SUMMARY.md
T
schalli 5e0e408f0f
Tessera CI/CD / Lint & Type Check (push) Successful in 46s
Tessera CI/CD / Tests (push) Successful in 56s
Tessera CI/CD / Build & Publish Images (push) Successful in 7s
docs(quick-260914-ebg): WINDOWS #29 abgeschlossen und verifiziert 6/6 — Zusammenfassung, Verifikation, Aktenstand
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-14 10:45:25 +02:00

14 KiB

phase, plan, subsystem, tags, requires, provides, affects, actuals, tech-stack, key-files, key-decisions, requirements-completed, coverage, duration, completed, status
phase plan subsystem tags requires provides affects actuals tech-stack key-files key-decisions requirements-completed coverage duration completed status
quick-260914-ebg 01 auth
nestjs
prisma
rbac
vitest
biome
phase provides
quick-260911-fh9 Zielrollen-Riegel-Vorlage in AuthService.adminResetPassword (T-FH9-04) — dieselbe Bedingung (user.role === SUPER_ADMIN && callerRole !== SUPER_ADMIN) wird hier in UserController.update()/remove() uebernommen
Zielrollen-Riegel in UserController.update() und UserController.remove(): ein ADMIN kann den SUPER_ADMIN seines eigenen Mandanten weder aendern noch loeschen
acht neue Tests (Test 9-16) in user.controller.spec.ts, Spec-Gesamtzahl 8 -> 16
WINDOWS #29 geschlossen (fixed); zwei neue Ledger-Eintraege #35 (Biome-Konfiguration defekt) und #36 (Frontend verschluckt 403 still)
user-management
auth
windows-ledger
tokens tasks commits plan_head_before
6669 3 3 e76c0f8a33
added patterns
Zielrollen-Riegel-Muster: Mandantengrenze IMMER vor Zielrollen-Pruefung, damit die Fehlermeldung nichts ueber die Rolle eines fremdmandantigen Benutzers verraet (jetzt an zwei Stellen: AuthService.adminResetPassword, UserController.update/remove)
created modified
apps/api/src/user/user.controller.ts
apps/api/src/user/user.controller.spec.ts
apps/api/src/auth/auth.service.ts
.planning/WINDOWS.md
Sechs ueberfluessige `as any`-Umschreibungen in den neuen Tests entfernt (Rule 1) — UpdateUserDto ist vollstaendig optional, die Objektliteral-Zuweisung ist ohne Umschreibung typkorrekt, und die Umschreibungen trieben die Biome-Warnungen der Spec-Datei ueber die Baseline (25)
WINDOWS-29
T-FH9-05
id description requirement verification human_judgment
D1 ADMIN kann SUPER_ADMIN des eigenen Mandanten weder per PATCH aendern (Kennwort, isActive, Rolle) noch per DELETE loeschen — ForbiddenException, Dienst nicht aufgerufen WINDOWS-29
kind ref status
unit apps/api/src/user/user.controller.spec.ts#Test 9: ein Mandanten-Administrator kann den SUPER_ADMIN des eigenen Mandanten weder übernehmen... pass
kind ref status
unit apps/api/src/user/user.controller.spec.ts#Test 13: ein Mandanten-Administrator kann den SUPER_ADMIN des eigenen Mandanten nicht löschen... pass
false
id description verification human_judgment
D2 Regressionsschutz: SUPER_ADMIN gegen SUPER_ADMIN und ADMIN gegen USER bleiben auf beiden Wegen erlaubt
kind ref status
unit apps/api/src/user/user.controller.spec.ts#Test 10, Test 11, Test 14, Test 15 pass
false
id description requirement verification human_judgment
D3 Reihenfolge: Mandantengrenze VOR Zielrollen-Pruefung in beiden Handlern — die Mandanten-Meldung verraet nichts ueber die Rolle eines fremdmandantigen Benutzers T-EBG-04
kind ref status
unit apps/api/src/user/user.controller.spec.ts#Test 12, Test 16 pass
false
id description verification human_judgment
D4 Falsifizierung: Rueckbau des Riegels macht genau Test 9 und Test 13 rot, byte-identisch wiederhergestellt
kind ref status
other git apply -R Rueckbau-Lauf, siehe Abschnitt Nachweis WINDOWS #29 — Rueckbau unten pass
false
id description requirement verification human_judgment
D5 Kopfkommentar AuthService.adminResetPassword nennt T-FH9-05 nicht mehr als offen T-FH9-05
kind ref status
other grep -c T-FH9-05 apps/api/src/auth/auth.service.ts -> 0 pass
false
id description verification human_judgment
D6 WINDOWS-Ledger: #29 fixed, #35 und #36 als eigene Nebenbefunde eingetragen, nicht mitgeschlossen
kind ref status
other node gsd-tools.cjs windows fixed 29; windows append (2x); Frontmatter-Gegenprobe pass
false
6min 2026-09-14 complete

Quick 260914-ebg: Zielrollen-Riegel in UserController.update/remove Summary

Zielrollen-Riegel (Vorlage aus AuthService.adminResetPassword, T-FH9-04) in UserController.update() und remove() eingezogen — ein ADMIN kann den SUPER_ADMIN seines Mandanten nicht mehr uebernehmen, aussperren, herabstufen oder loeschen; acht neue Tests, Falsifizierung durch Rueckbau bestanden, WINDOWS #29 geschlossen.

Performance

  • Duration: 6 min
  • Started: 2026-09-14T10:33:00+02:00 (Baseline-Lauf vor Task 1)
  • Completed: 2026-09-14T10:38:29+02:00 (Push)
  • Tasks: 3
  • Files modified: 4

Accomplishments

  • Zielrollen-Riegel in UserController.update() (nach der Mandantengrenze, vor der dto.role-Pruefung) und UserController.remove() (nach der Mandantengrenze, vor userService.delete), jeweils mit ForbiddenException und Kommentar, der auf WINDOWS #29 und die Vorlage T-FH9-04 verweist
  • Acht neue Tests (Test 9-16) in user.controller.spec.ts: drei Angriffsformen gegen den SUPER_ADMIN (Kennwort, isActive, Rolle), zwei Regressionstests (SUPER_ADMIN gegen SUPER_ADMIN, ADMIN gegen USER) je Handler, zwei Ordnungstests (Mandantengrenze vor Zielrolle)
  • Falsifizierung: Rueckbau des Task-1-Commits macht genau Test 9 und Test 13 rot, danach byte-identisch wiederhergestellt
  • Kopfkommentar AuthService.adminResetPassword fortgeschrieben — die alte Ledger-Kennung T-FH9-05 kommt in der Datei nicht mehr vor
  • WINDOWS #29 auf fixed gesetzt; zwei neue, eigenstaendige Nebenbefunde #35 (Biome-Konfiguration defekt) und #36 (Frontend verschluckt 403 still) eingetragen, nicht mit #29 mitgeschlossen

Task Commits

Alle drei Aufgaben wurden einzeln committet:

  1. Task 1: Zielrollen-Riegel in update() und remove() — Tests zuerst (RED), dann Riegel (GREEN) - 759ea3b (fix)
  2. Task 2: Falsifizierung durch Rueckbau, Kopfkommentar der Vorlage nachziehen, Gesamt-Gates - 63f9df0 (docs)
  3. Task 3: Ledger — #29 schliessen, zwei Nebenbefunde eintragen, pushen - 70d007b (docs)

Task 1 ist TDD: Tests wurden vor dem Riegel geschrieben (RED), dann der Riegel eingezogen (GREEN) — beides im selben Commit, da RED und GREEN Teil derselben Aufgabe und desselben Nachweises sind.

Nachweis WINDOWS #29 — Rueckbau

RED-Lauf (Task 1, Schritt A — vor dem Riegel, Tests bereits vorhanden):

Test Files  1 failed (1)
     Tests  2 failed | 14 passed (16)

Rot: Test 9: ein Mandanten-Administrator kann den SUPER_ADMIN des eigenen Mandanten weder übernehmen (Kennwort setzen), noch aussperren (isActive=false), noch herabstufen (role=USER) — alle drei Angriffsformen werden mit der Zielrollen-Ausnahme abgelehnt, und der Dienst wird in keinem der drei Fälle aufgerufen (Fehler: Cannot destructure property 'passwordHash' of 'updated' as it is undefined statt der erwarteten Cannot modify a SUPER_ADMIN user) und Test 13: ein Mandanten-Administrator kann den SUPER_ADMIN des eigenen Mandanten nicht löschen — die Zielrollen-Ausnahme greift, und der Dienst wird nicht aufgerufen (Promise loeste mit { message: 'User deleted' } auf statt abzulehnen). Alle anderen 14 Tests gruen.

Nach dem Riegel (GREEN): Tests 16 passed (16).

Falsifizierungs-Rueckbau (Task 2, Schritt A — gegen den committeten Stand):

git show HEAD -- apps/api/src/user/user.controller.ts > $SCR/riegel.patch && git apply -R $SCR/riegel.patch
pnpm -C apps/api exec vitest run src/user/user.controller.spec.ts

Ergebnis, woertlich:

Test Files  1 failed (1)
     Tests  2 failed | 14 passed (16)

Rot exakt dieselben zwei: Test 9 (AssertionError: expected [Function] to throw error including 'Cannot modify a SUPER_ADMIN user' but got 'Cannot destructure property \'passwor…') und Test 13 (AssertionError: promise resolved "{ message: 'User deleted' }" instead of rejecting). Die anderen 14 Tests blieben gruen — der Riegel ist damit als notwendig fuer genau diese zwei Verhaltensnachweise belegt.

Wiederherstellung:

git checkout -- apps/api/src/user/user.controller.ts
git status --porcelain apps/api/src/user/user.controller.ts

Ausgabe der zweiten Zeile: leer (byte-identisch wiederhergestellt). Spec danach erneut Tests 16 passed (16).

Gates

  1. pnpm -C apps/api exec vitest run -> Test Files 62 passed (62) / Tests 1028 passed (1028) (Baseline 1020/62 plus 8 neue Tests)
  2. pnpm -C apps/api exec tsc --noEmit; echo EXIT=$? -> EXIT=0
  3. D=$(git diff --stat 37a2f73 -- . ':!.planning'); echo GIT_EXIT=$?; tail -n1 <<< "$D" -> GIT_EXIT=0, 3 files changed, 136 insertions(+), 2 deletions(-)
  4. grep -cE "^\| 29 \|.*\| fixed \|" .planning/WINDOWS.md -> 1

Biome-Zahlentripel (Ersatzkonfiguration im Scratchpad, relativ zur Baseline — biome.json im Repo unangetastet):

Datei Fehler Warnungen Infos Baseline-Warnungen
apps/api/src/user/user.controller.ts 0 22 2 22
apps/api/src/user/user.controller.spec.ts 0 25 0 25
apps/api/src/auth/auth.service.ts 0 20 1 20

Alle drei Dateien treffen die Baseline exakt (nach dem Rule-1-Nebenfund unten). Kein neues any, kein neuer Import.

git status --porcelain nach Task 3 (Arbeitsbaum sauber):

(leer)

git log e76c0f8..HEAD:

70d007b docs(quick-260914-ebg): Ledger — WINDOWS #29 fixed, Nebenbefunde Biome-Konfiguration und stilles 403 im Frontend eingetragen
63f9df0 docs(quick-260914-ebg): Kopfkommentar adminResetPassword — Schwesterwege PATCH/DELETE /users/:id geschlossen (WINDOWS #29)
759ea3b fix(quick-260914-ebg): Zielrollen-Riegel in UserController.update/remove — ADMIN kann SUPER_ADMIN nicht mehr aendern oder loeschen (WINDOWS #29)

Files Created/Modified

  • apps/api/src/user/user.controller.ts - Zielrollen-Riegel in update() und remove(), je ein Kommentarblock mit Verweis auf WINDOWS #29 und T-FH9-04
  • apps/api/src/user/user.controller.spec.ts - neuer describe-Block mit acht Tests (Test 9-16), Spec-Gesamtzahl 16
  • apps/api/src/auth/auth.service.ts - Kopfkommentar adminResetPassword fortgeschrieben (T-FH9-05 nicht mehr offen)
  • .planning/WINDOWS.md - #29 fixed, #35 und #36 neu (quick-260914-ebg, deviation)

Decisions Made

  • Zielrollen-Riegel als eigenstaendige if-Pruefung nach der Mandantengrenze eingezogen, nicht als Erweiterung der bestehenden dto.role-Pruefung — die bestehende Pruefung sichert die NEUE Rollenzuweisung, der neue Riegel sichert das bereits vorhandene ZIEL; beide bleiben unabhaengig lesbar
  • Mandantengrenze bewusst VOR der Zielrollen-Pruefung belassen (nicht umgestellt), damit ein Ordnungsfehler durch die Ordnungstests (Test 12, Test 16) sofort rot wird

Deviations from Plan

Auto-fixed Issues

1. [Rule 1 - Bug] Sechs ueberfluessige as any-Umschreibungen in den neuen Tests entfernt

  • Found during: Task 2, Schritt C.3 (Biome-Gate)
  • Issue: Die acht neuen Tests in user.controller.spec.ts trugen sechs as any-Umschreibungen bei den UpdateUserDto-Objektliteralen ({ password: '...' } as any usw.). Der Plan hatte in planning_measurements bereits festgehalten, dass UpdateUserDto vollstaendig optional ist und die Objektliterale ohne Umschreibung zuweisbar sind — die Umschreibungen waren unnoetig und trieben die Biome-Warnungen von user.controller.spec.ts von der Baseline 25 auf 31 (relative Ersatzkonfiguration, noExplicitAny-Familie).
  • Fix: Alle sechs as any an den betroffenen Aufrufstellen entfernt (Test 9, Test 10, Test 11, Test 12).
  • Files modified: apps/api/src/user/user.controller.spec.ts
  • Verification: pnpm -C apps/api exec vitest run src/user/user.controller.spec.ts weiterhin Tests 16 passed (16); Biome-Gate danach Found 25 warnings. (Baseline exakt getroffen)
  • Committed in: 63f9df0 (Task 2 Commit, zusammen mit dem Kopfkommentar in auth.service.ts, da beide Aenderungen aus demselben Gate-Durchlauf stammen)

Total deviations: 1 auto-fixed (Rule 1) Impact on plan: Reine Aufraeumarbeit an eigenem, in Task 1 neu geschriebenem Testcode — kein Scope-Creep, keine Verhaltensaenderung, Biome-Schwelle nicht angehoben, sondern die Baseline exakt wiederhergestellt.

Nebenbefunde

#35 (Biome-Konfiguration defekt, biome.json): Biome ist im Bestand nicht lauffaehig — biome.json traegt den in Biome 2.5.0 unbekannten Schluessel organizeImports (gehoert unter assist), und es fehlt javascript.parser.unsafeParameterDecoratorsEnabled, ohne den jeder NestJS-Parameter-Dekorator ein Parse-Fehler ist. Der CI-Schritt „Lint" ruft pnpm lint = turbo lint, doch keine App hat ein lint-Skript — der Schritt ist ein Leerlauf, der gruen meldet. Als eigener Ledger-Eintrag festgehalten (nicht in #29 mitgeschlossen), biome.json liegt ausserhalb der Erlaubnisliste dieses Plans.

#36 (Frontend verschluckt 403 still, apps/web/.../admin/users/page.tsx): handleSubmit und handleDelete pruefen nur res.ok ohne else-Zweig und fangen mit leerem catch — ein 403 fuehrt zu keiner sichtbaren Reaktion. Bestehendes Verhalten fuer alle 403-Wege, aber seit diesem Plan (WINDOWS #29) fuer einen ADMIN im Alltag erstmals erreichbar, weil die SUPER_ADMIN-Zeile in der eigenen Benutzerliste steht und Aendern/Loeschen darauf jetzt 403 liefert. Als eigener Ledger-Eintrag festgehalten, Frontend von diesem Plan nicht geaendert (ausserhalb der Erlaubnisliste).

Issues Encountered

None - die Umsetzung folgte dem Plan, bis auf den in „Deviations from Plan" dokumentierten Rule-1-Nebenfund.

User Setup Required

None - keine externe Konfiguration erforderlich.

Next Phase Readiness

  • WINDOWS #29 geschlossen, Rechteausweitung ADMIN gegen SUPER_ADMIN in beiden Schwesterwegen (adminResetPassword, UserController.update/remove) geschlossen
  • Zwei Nebenbefunde (#35 Biome, #36 Frontend-403) offen und im Ledger sichtbar — kein Blocker fuer diesen Plan, aber vor dem naechsten Milestone-Abschluss zu pruefen
  • Kein laufender Milestone begonnen; v1.2 bleibt abgeschlossen (siehe STATE.md)

Phase: quick-260914-ebg Completed: 2026-09-14

Self-Check: PASSED

Alle vier geaenderten Dateien und die SUMMARY-Datei selbst gefunden; alle drei Task-Commits (759ea3b, 63f9df0, 70d007b) in der Historie gefunden.