Files
tessera-ctl/.planning/quick/260921-bi2-lint-rueckstand-abbauen-mechanische-fixe/260921-bi2-SUMMARY.md
T
schalli c001a081c2
Tessera CI/CD / Lint & Type Check (push) Successful in 51s
Tessera CI/CD / Tests (push) Successful in 1m5s
Tessera CI/CD / Desktop-Pakete bauen (push) Successful in 5m24s
Tessera CI/CD / Build & Publish Images (push) Successful in 4m15s
docs(quick-260921-bi2): Lint-Rueckstand 2923 -> 465, Akte und Verifikation
Zusammenfassung, Verifikation und STATE.md zum Quick-Vorgang 260921-bi2.

Kernbefund: Biomes als "safe" eingestufte Korrektur style/useImportType
zerstoert in apps/api die NestJS-Abhaengigkeitsspritze — das erzeugte
__metadata("design:paramtypes", [...]) kollabiert zu [Function, ...] und
die API startet nicht mehr, waehrend tsc gruen bleibt und alle 1124
API-Tests gruen bleiben (kein Test ruft createTestingModule auf).
Deshalb ein zweiter, auf apps/api/** begrenzter overrides-Eintrag.

Nachweis fuer "kein Verhaltenswechsel" ist nicht die Testsuite, sondern
ein sha256 ueber alle 593 erzeugten __metadata-Zeilen (6e1583f1...),
vor und nach dem Umbau identisch. Dazu Klicktest am laufenden System
mit den echten Abbildern: API healthy, Abbrechen legt nichts an,
Speichern legt an, ADMIN sieht auf der SUPER_ADMIN-Zeile nur Details,
abgewiesene Server-Antworten erscheinen sichtbar.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TPPB4ApQxzSU1rwV2Ffj9J
2026-09-21 10:02:44 +02:00

25 KiB
Raw Blame History

phase, plan, subsystem, tags, requires, provides, affects, actuals, tech-stack, key-files, key-decisions, requirements-completed, duration, completed, status
phase plan subsystem tags requires provides affects actuals tech-stack key-files key-decisions requirements-completed duration completed status
quick-260921-bi2 01 tooling
biome
lint
a11y
nestjs
decorator-metadata
i18n
biome.json mit genau zwei zielgenauen overrides (Testdateien / apps/api) statt eines unueberschaubaren 2923er-Rueckstands
45 maschinell erzeugte, von Hand gelesene Korrekturen ueber vier sichere und fuenf unsichere Biome-Regeln
15 untersuchte Fundstellen toten Codes: 10 folgenlos entfernt, 1 umbenannt (NestJS- Parameterposition), 4 als benannte Folgeaufgaben gemeldet statt repariert
155 von Hand erledigte Barrierefreiheits-Fundstellen ueber sechs Regeln (Symbole, Schaltflaechentyp, Beschriftungsbindung, Rollen/ARIA-Merkmale, Tab-Reihenfolge)
Entwickleranleitung auf Endstand 465/386/79 gebracht, beide Ausnahmen begruendet, Folgeaufgaben benannt
ci-lint-gate
apps/web-a11y
apps/api-di
tokens tasks commits
37573 3 13
added patterns
biome.json overrides sind pfadgebunden (apps/api/**), nie repo-weit mit --only=<regel> angewendet -- --only schaltet eine per Konfiguration abgeschaltete Regel wieder an.
Bei einer Regel ohne gesicherten Fix zuerst den Diff lesen (--write ohne --unsafe testen), danach --unsafe pruefen, danach den ganzen Diff lesen -- nie ungeprueft anwenden.
a11y-Fixes koennen sich gegenseitig verschieben: eine Regel loesen kann eine ANDERE (zurueckgestellte) Regel neu anschlagen, wenn ein Element seine interaktive Klassifikation verliert (role=button entfernt -> noStaticElementInteractions greift auf die verbliebenen Drag-Handler). Nach jedem Einzel-Fix die komplette Regelmenge (in Scope UND zurueckgestellt) neu messen, nicht nur die Zielregel.
created modified
biome.json
docs/anleitung-entwicklung.md
apps/api/src/** (45 maschinelle Korrekturen + toter Code, Aufgabe 2)
apps/web/src/** (a11y, Aufgabe 3, beide Teillieferungen)
apps/desktop/src/setup.html
apps/web/src/messages/de.json
apps/web/src/messages/en.json
useImportType in apps/api/** abgeschaltet statt maschinell angewendet: emitDecoratorMetadata erzeugt __metadata(design:paramtypes,...), das NestJS zur Abhaengigkeitsaufloesung liest; import type entfernt den Wert-Import und ersetzt die erzeugten Typen durch Function- Platzhalter. 61 von 65 Dateien mit Abhaengigkeitsdaten waeren beschaedigt worden, bei gruenem tsc und gruenen 1124 Tests (kein Test ruft createTestingModule auf) -- der Fehler waere durch jedes Tor dieses Projekts unbemerkt hindurchgegangen.
noUselessSwitchCase (1 Fundstelle, tender-normalizer.service.ts:60) bewusst NICHT angewendet: die Fallmarke dokumentiert, warum der Standardzweig auf diesem Weg bleiben muss; die Regel sieht nur den Code, nicht die Absicht dahinter.
useSemanticElements (4 Fundstellen) wurde entgegen der urspruenglichen Einordnung in PLAN.md (dort unter D-05 zurueckgestellt) in Teillieferung B doch bearbeitet -- Abweichung von der Vorgabe, siehe Deviations.
DropZone.tsx: Datei-Entfernen-Schaltflaeche als Geschwister statt verschachtelt in der Drop-Flaeche (kein <button> darf ein zweites <button> enthalten); Drag-Handler wanderten von der Flaechen-<div> auf die Flaechen-<button>, sonst waere ein 'statisches Element mit Ereignis-Handler' entstanden und haette zwei zurueckgestellte Regeln neu ausgeloest.
admin-sidebar.tsx/settings-sidebar.tsx: role=navigation vom <aside> aufs bereits vorhandene <nav> verschoben statt das <aside> in ein zweites <nav> zu verwandeln -- sonst waere ein doppeltes Navigations-Landmark entstanden.
LINT-BACKLOG
~150min (Teillieferung B; Gesamtvorgang laenger, ueber mehrere Sitzungen) 2026-09-21 complete

Quick-Vorgang 260921-bi2: Lint-Rueckstand abbauen (mechanische Fixe) Summary

Lint-Rueckstand von 2923 auf 465 Befunde gesenkt (0 Fehlerstufe durchgehend) — durch eine begruendete, pfadgebundene Konfigurationsbereinigung, einen von Hand gelesenen maschinellen Durchgang und 155 handgeschriebene Barrierefreiheits-Korrekturen, ohne die NestJS- Abhaengigkeitsaufloesung anzutasten.

Performance

  • Aufgabe 1 (Konfiguration): Commit 8d1c8f3
  • Aufgabe 2 (maschinell + toter Code): Commits 3811578, 636fe0d
  • Aufgabe 3, Teillieferung A (a11y — Symbole, Schaltflaechentyp, Layout/Formulare): Commits e76f3b8, 4cff316, ae82125, 278aedb, 969fd01, 27a6e29, 73ac08a
  • Aufgabe 3, Teillieferung B (a11y — Rollen, Semantik, Tab-Reihenfolge, Beschriftungsbindung): Commits 21c85a8, c79bafa
  • Abschlussarbeiten (Entwickleranleitung, dieser Vorgang): Commit 97a6836
  • Tasks: 3 (laut PLAN.md), ueber mehrere Sitzungen in zwei Teillieferungen ausgefuehrt
  • Dateien geaendert (gesamter Vorgang): 110 (biome.json, docs, 2 i18n-Kataloge, ~106 Quell- und Testdateien)
  • Commits gesamt: 13

Vorher/Nachher

Durchgang gesamt echter Quelltext Testdateien Fehlerstufe
Start 2923 856 2067 0
Aufgabe 1 — Konfiguration 754 633 121 0
Aufgabe 2 — maschinell + toter Code 621 542 79 0
Aufgabe 3A — a11y (Symbole, Schaltflaechen, Layout) 497 418 79 0
Aufgabe 3B — a11y (Rollen, Semantik, Beschriftungen) — Endstand 465 386 79 0

Der Zielwert im PLAN.md-Text lautete 466; der korrekte Wert ist 465, weil Aufgabe 2 beim Entfernen einer unbenutzten catch (e: any)-Bindung in calendar.service.ts inzidentell einen zusaetzlichen noExplicitAny-Befund mitgenommen hat (288 statt 289 in echtem Quelltext, 0 in Testdateien — die Testdatei-Ausnahme aus Aufgabe 1 reicht weiterhin nachweislich nicht in Produktivcode hinein). Das ist keine nachtraeglich "passend gemachte" Zahl, sondern die gemessene Tatsache; im Endstand wurde nichts unternommen, um wieder auf 466 zu kommen.

Aufgabe 1: Konfiguration bereinigen

biome.json traegt seither genau zwei overrides-Eintraege, sonst nichts an der Regelmenge geaendert; security kommt in der Datei nicht vor (erbt weiterhin error).

  1. Testdateien (**/*.spec.ts, **/*.spec.tsx, **/*.test.ts, **/*.test.tsx): suspicious/noExplicitAny auf off. Begruendung: any haengt dort ausnahmslos an Attrappen; geprueft mit grep -rln "^export" --include=*.spec.ts ... — keine Testdatei exportiert ein Symbol, keine Nicht-Testdatei fuehrt eine Testdatei ein.
  2. apps/api/**: style/useImportType auf off. Das ist die wichtigste Einzelentscheidung des gesamten Vorgangs — siehe naechster Abschnitt.
  3. Die fehlerhafte Fixture-Ausnahme (__fixtures__** statt __fixtures__) korrigiert; Biome meldte das selbst als lint/suspicious/useBiomeIgnoreFolder.

Der useImportType/NestJS-Befund — der wichtigste Einzelfund dieses Vorgangs

style/useImportType ist mit 224 Befunden die groesste Einzelregel, 222 davon in apps/api. Biome stuft die Korrektur als „sicher" ein und wendet sie standardmaessig ohne --unsafe an. Sie ist es in diesem Projekt aber nicht: apps/api/tsconfig.json hat emitDecoratorMetadata eingeschaltet, und NestJS loest seine Konstruktor-Abhaengigkeiten zur Laufzeit ueber genau die Daten auf, die der TypeScript-Compiler aus den Parametertypen erzeugt (__metadata("design:paramtypes", [...])). import type markiert einen Import als reinen Typ-Import; der Compiler entfernt ihn vollstaendig aus dem erzeugten JavaScript — inklusive der Werte, die __metadata braucht. Probelauf an auth.service.ts beim Planen: vorher __metadata("design:paramtypes", [prisma_service_1.PrismaService, ...]), nachher __metadata("design:paramtypes", [Function, Function, Function, Function, Function, Function]), und die zugehoerige require-Zeile verschwindet ersatzlos. Ueber den ganzen Workspace gemessen: 61 von 65 Dateien mit Abhaengigkeitsdaten waeren beschaedigt worden. Die API startet danach nicht mehr — jeder DI-Aufloesungsversuch traefe auf Function statt auf die echte Klasse.

Der entscheidende Punkt: kein Tor dieses Projekts haette das bemerkt. pnpm type-check bleibt gruen (TypeScript prueft Typen, nicht erzeugte Laufzeit-Metadaten). Und kein einziger der 1124 API-Tests waere rot geworden, denn grep -rl createTestingModule apps/api/src liefert 0 Treffer — der gesamte Testbestand startet den NestJS-Dependency-Injection-Container nirgends, er testet Services/Controller mit von Hand konstruierten Abhaengigkeiten. Ein automatischer, "sicherer" Fix haette die Anwendung im Betrieb lautlos zerstoert, waehrend jede automatisierte Pruefung dieses Projekts weiterhin gruen gemeldet haette.

Biome raeumt das Problem in der eigenen Regelbeschreibung ein (biome explain useImportType → Abschnitt „Caveat with TypeScript experimental decorators") und empfiehlt dort woertlich, die Regel bei solchen Dekoratoren abzuschalten. Aufgabe 1 folgt dieser Empfehlung mit einem auf apps/api/** begrenzten Eintrag — eine bewusste Abweichung von der generellen mechanischen-Regeln-Vorgabe (D-02), die ausschliesslich deshalb geschieht, weil "kein Verhaltenswechsel" (D-07) hier Vorrang vor einer kleineren Zahl hat.

Nachweis, nicht Vermutung: Vor dem maschinellen Durchgang (Aufgabe 2) wurde ein Fingerabdruck ueber alle erzeugten __metadata-Zeilen genommen (593 Zeilen, sha256 6e1583f1eb72a089eb0ed98f81158b54a9fbd40dbf41371292725f36ef764300). Nach Abschluss aller drei Aufgaben — Konfiguration, maschineller Durchgang, Barrierefreiheit — ist dieser Fingerabdruck Zeichen fuer Zeichen identisch, gerade jetzt erneut gemessen:

$ SNAP=$(mktemp -d); pnpm --filter @tessera/api exec tsc --outDir "$SNAP"
$ grep -rh '__metadata(' "$SNAP" | wc -l
593
$ grep -rh '__metadata(' "$SNAP" | sort | sha256sum
6e1583f1eb72a089eb0ed98f81158b54a9fbd40dbf41371292725f36ef764300  -

Das ist der tragende Nachweis dieses gesamten Vorgangs — nicht der gruene Testlauf, der diesen spezifischen Schaden nachweislich nicht aufdecken kann.

Aufgabe 2: Maschinelle Korrekturen und toter Code

(A) Vier Regeln mit gesichertem Fix (--write ohne --unsafe): style/useImportType (pfadgebunden auf apps/web packages, NIE repo-weit — ein repo-weiter Lauf haette die Ausnahme aus Aufgabe 1 wirkungslos ausgehaengt und 201 import type-Zeilen nach apps/api geschrieben, beim Planen genau so gemessen), complexity/noUselessEscapeInRegex, style/useConst, style/useExponentiationOperator.

(B) Fuenf Regeln mit --unsafe-Fix, Diff vollstaendig von Hand gelesen (~100 Zeilen): style/useNodejsImportProtocol, complexity/useLiteralKeys, complexity/useOptionalChain, style/useTemplate, correctness/useParseIntRadix. Zwei Dateien brauchten besondere Aufmerksamkeit:

  • ldap.service.ts (25 der 31 useLiteralKeys-Aenderungen): Verzeichnis-Merkmale (objectGUID, sAMAccountName, cn, ou, mail) zeichenweise gegengelesen — ein verschluckter Grossbuchstabe macht den AD-Abgleich still leer, und AD ist in diesem Projekt bewusst nur lesend angebunden, faellt also erst beim Anmelden auf.
  • jwt.strategy.ts / auth.service.ts: Verkuerzungen im Anmeldeweg (useOptionalChain) geprueft, dass eine fehlende Sitzung weiterhin zur Abweisung fuehrt, nicht zum Durchwinken.

Die sechste ungesicherte Regel, complexity/noUselessSwitchCase (1 Fundstelle, tender-normalizer.service.ts:60), wurde bewusst NICHT angewendet. Der Vorschlag wuerde eine Fallmarke streichen, die unmittelbar ueber einem Kommentar steht, der erklaert, warum der Standardzweig genau auf diesem Weg bleiben muss. Die Marke dokumentiert Absicht, die der Regel entgeht. Sie steht weiterhin sichtbar in der Zaehlung (1), nicht unterdrueckt — eine Unterdrueckung waere hier unehrlicher als das sichtbare Stehenlassen, weil sie wie eine Erledigung aussehen wuerde, ohne eine zu sein.

(C) Toter Code, 15 Fundstellen, drei Gruppen:

  1. Echt tot, folgenlos entfernt (10): nicht benutzte Fehlervariablen in calendar.service.ts (Zeilen 321, 358), cert-manager.service.ts (305, 679), dkv-parser.service.ts (42); nicht benutzte Einfuhren in create-calendar-source.dto.ts:2; nicht benutzte Funktion forSystemQuery in rls-scratch-check.mjs:226; und login/page.tsx:21 (unbenutzter Wegweiser — Weiterleitung ist nachweislich anderswo geloest, daher entfernt ohne Meldung).
  2. Nicht entfernbar, umbenannt (1): current-user.decorator.ts:4 — data ist der erste von zwei positionsgebundenen NestJS-Parametern; Streichen wuerde den zweiten verschieben. Stattdessen mit fuehrendem Unterstrich gekennzeichnet.
  3. Symptome, gemeldet statt repariert (4 — siehe naechster Abschnitt).

Die vier gemeldeten Symptomfunde (D-03) — offene Folgeaufgaben

Diese vier unbenutzten Werte waren beim Lesen KEIN totes Code-Rauschen, sondern der Hinweis auf eine echte Luecke. Sie zu schliessen waere ein Verhaltenswechsel gewesen, den dieser lint-abbauende Vorgang nicht treffen durfte (D-07):

  1. force-password-change.interceptor.ts:53 liest das HTTP-Verfahren in eine Variable und befragt sie nie — die Freigabeliste unterscheidet also nicht zwischen Lese- und Schreibzugriff auf die freigegebenen Wege. Variable entfernt, Luecke hier als eigene Folgeaufgabe benannt.
  2. change-password/page.tsx:11-12 hielt Wegweiser und Benutzerablage vor, benutzte beide nicht. Bestaetigt beim Lesen: nach erfolgreichem Wechsel wird weder weitergeleitet noch die Benutzerablage aufgefrischt — bei erzwungenem Wechsel bleibt die Person auf der Seite stehen. Die drei Bindungen entfernt, Befund hier als Folgeaufgabe benannt.
  3. VehicleTable.tsx:164 setzte einen Laufzustand fuers Loeschen, las ihn aber nie — die Loeschschaltflaeche hat also keinen Besetztzustand und laesst sich doppelt ausloesen. Nur die lesende Bindung entfernt, die setzende blieb; Befund hier als Folgeaufgabe benannt.
  4. SplitTab.tsx:20 bekam die Uebersetzungsfunktion und benutzte sie nicht — ein Hinweis auf fest verdrahtete Texte in diesem Reiter. Parameter entfernt, Befund hier als Folgeaufgabe benannt.

(Ein fuenfter untersuchter Kandidat, login/page.tsx:21, gehoerte urspruenglich zur selben "Symptom"-Kategorie in der Planung, stellte sich beim Lesen aber als echt folgenlos heraus — siehe Gruppe 1 oben. Er wird hier zur Vollstaendigkeit genannt, braucht aber keine eigene Folgeaufgabe.)

Nachweis fuer den gesamten maschinellen Durchgang: 45 Quelldateien geaendert, Diff zeilenbilanziert (keine Formatierung mitgelaufen, D-08), NestJS-Metadaten-Fingerabdruck unveraendert (siehe oben), beide Testlaeufe punktgleich gruen.

Aufgabe 3: Barrierefreiheit von Hand (beide Teillieferungen)

155 Fundstellen in 53 Dateien, durchgehend Handarbeit — fuer alle sechs bearbeiteten Regeln bot Biome weder einen gesicherten noch ungesicherten Fix (einzige Ausnahme: noRedundantRoles mit 3 Dateien unter --unsafe, Ergebnis trotzdem gelesen).

Teillieferung A (vorherige Sitzung, Commits e76f3b8 … 73ac08a)

  • a11y/noSvgWithoutTitle (71): je Symbol entschieden — begleitet es sichtbaren Text, wird es als Schmuck vor der Vorlesehilfe verborgen; steht es allein, bekommt es einen Titel, der die Bedienung nennt (Uebersetzungskatalog, wo die Datei schon uebersetzt ist). Zwei Fundstellen ausserhalb der React-Oberflaeche: apps/web/src/app/icon.svg (Bildmarke, Titel mit Produktnamen) und apps/desktop/src/setup.html:173 (Desktop-Einrichtungsseite).
  • a11y/useButtonType (52): nur 3 von 25 betroffenen Dateien enthalten ein Formular (admin/tenants/page.tsx, admin/users/page.tsx, admin/ldap/page.tsx); dort war der Absendeknopf je bereits richtig ausgezeichnet (1/1/2), die restlichen 16 Fundstellen waren Neben-Schaltflaechen (Abbrechen, Schliessen, Zeilenaktionen), die beim Klick ungewollt absendeten — bekamen type="button". In den uebrigen 22 Dateien ohne Formular ist die Auszeichnung reine Absicherung.
  • Zwei neue Uebersetzungsschluessel (LDAP-Standardzuordnung, Suchbutton), in de.json UND en.json ergaenzt (Commit 3811578).

Teillieferung B (diese Sitzung, Commits 21c85a8, c79bafa)

Die verbleibenden fuenf zugewiesenen Regeln (32 Fundstellen) auf 0 gebracht:

  • a11y/noRedundantRoles (4): maschineller --unsafe-Fix, gelesen. Entfernte role="button"/role="time"/role="combobox" von button/time/select-Elementen, wo die Rolle bereits implizit ist.
  • a11y/useAriaPropsForRole (1): entfiel automatisch mit obigem Fix — das <select role="combobox"> in search-widget.tsx verlangte die fehlenden ARIA-Attribute nur wegen der ueberfluessigen Rolle.
  • a11y/useSemanticElements (4): admin-sidebar.tsx/settings-sidebar.tsx tragen role="navigation" jetzt am bereits vorhandenen <nav> statt am <aside> (kein doppeltes Landmark); widget-wrapper.tsx ist jetzt ein echtes <article> statt div role="article"; DropZone.tsx trennt die "Entfernen"-Schaltflaeche als Geschwister ab, damit die Drop-Flaeche selbst ein echtes <button> werden kann (ein <button> darf kein zweites <button> verschachteln) — Klick- UND Drag-Handler wanderten dabei auf den <button>, sonst waere die umgebende <div> ein "statisches Element mit Ereignis-Handler" geworden und haette die zurueckgestellten Regeln noStaticElementInteractions/noNoninteractiveElementInteractions neu ausgeloest (geprueft — geschah zunaechst versehentlich, wurde vor dem Commit korrigiert).
  • a11y/noNoninteractiveTabindex (1): calculator-widget.tsx traegt jetzt tabIndex={-1} statt {0}. Die Zifferntasten sind bereits echte <button>-Elemente und damit selbst Teil der Tab-Reihenfolge; Tastendruecke erreichen handleKeyboard weiterhin per Bubbling, sobald eine Taste fokussiert ist — Verhalten unveraendert, nur ein wirkungsloser Tab-Stopp auf dem Container selbst entfaellt.
  • a11y/noLabelWithoutControl (22): jede Beschriftung ueber htmlFor/id an ihr Feld gebunden — in Formularen mit wiederholten Feldnamen (LDAP, Benutzer, Mandanten) ueber seitenweit eindeutige, praefixierte Kennungen (ldap-*, user-*, tenant-*). Sonderfall calendar-source-form.tsx: die Farbauswahl beschriftet eine ganze Gruppe von Farb-Schaltflaechen, kein einzelnes Feld — dafuer fieldset/legend statt htmlFor/id (Rand/Abstand zurueckgesetzt, damit sich am Erscheinungsbild nichts aendert); eine Umwandlung in <span> haette die Assoziation entfernt statt sie herzustellen und wurde darum nicht gewaehlt.

Was bewusst stehen bleibt (30 Befunde, D-05)

Diese fuenf Regeln wurden NICHT bearbeitet, weil jede eine Gestaltungsentscheidung oder einen Verhaltenswechsel verlangt, den dieser Vorgang nicht treffen darf. Gepruefte, unveraenderte Zaehlung nach Teillieferung B:

Regel Befunde Warum zurueckgestellt
a11y/noNoninteractiveElementInteractions 11 verlangt die Entscheidung, ob ein geklickter Bereich eine echte Bedienung wird oder der Klick verschwindet
a11y/noStaticElementInteractions 5 dieselbe Entscheidung, andere Fundstellenmenge
a11y/useKeyWithClickEvents 5 verlangt einen Tastaturweg, den es heute nicht gibt — neue Bedienung, kein Aufraeumen
a11y/useAriaPropsSupportedByRole 5 verlangt einen Blick auf jede gesetzte Rolle einzeln, teils mit Gestaltungsfolgen
a11y/noAutofocus 4 Entfernen verschiebt den Eingabefokus beim Seitenaufruf — Verhaltenswechsel (D-07 verbietet ihn hier)

Keine dieser Regeln wurde herabgestuft oder abgeschaltet — sie stehen weiterhin auf warn und tauchen in keiner overrides-Ausnahme auf.

Verifikation (soeben erneut ausgefuehrt)

--- in-scope (Ziel 0) ---
noLabelWithoutControl 0
noRedundantRoles 0
useSemanticElements 0
useAriaPropsForRole 0
noNoninteractiveTabindex 0

--- zurueckgestellt (muss unveraendert bleiben) ---
noNoninteractiveElementInteractions 11
useKeyWithClickEvents 5
noStaticElementInteractions 5
useAriaPropsSupportedByRole 5
noAutofocus 4

Endstand: total 465 real 386 test 79 errors 0
  • apps/api und packages unberuehrt seit 636fe0d: git diff --name-only 636fe0d..HEAD -- apps/api packages → leer.
  • NestJS-__metadata-Fingerabdruck: 593 Zeilen, sha256 6e1583f1eb72a089eb0ed98f81158b54a9fbd40dbf41371292725f36ef764300 — identisch zum Ausgangswert.
  • apps/web Vitest: Test Files 66 passed (66), Tests 459 passed (459).
  • apps/api Vitest: Test Files 69 passed (69), Tests 1124 passed (1124).
  • pnpm type-check: 4/4 erfolgreich.
  • pnpm lint --force: 5/5 erfolgreich, 0 Befunde der Stufe Fehler (nur Warnungen/Info).
  • de/en-Uebersetzungskataloge: 892 Schluessel je Katalog, Mengen identisch (0 nur-de, 0 nur-en).
  • noExplicitAny nach der Testdatei-Ausnahme: 288 in echtem Quelltext (siehe Abschnitt "Vorher/Nachher" fuer die 289→288-Abweichung), 0 in Testdateien.

Deviations from Plan

Auto-fixed Issues

1. [Rule 3 - Blocking] Handler-Typannotation in DropZone.tsx nach Restrukturierung

  • Found during: Teillieferung B, useSemanticElements-Fix an DropZone.tsx
  • Issue: Nach dem Verschieben der Drag-Handler von der <div> auf die <button> blieb die Typannotation React.DragEvent<HTMLDivElement> stehen; pnpm type-check schlug mit zwei TS2322-Fehlern fehl.
  • Fix: Annotation auf React.DragEvent<HTMLButtonElement> korrigiert.
  • Files modified: apps/web/src/app/(portal)/modules/cert-manager/components/DropZone.tsx
  • Verification: pnpm type-check danach 4/4.
  • Committed in: 21c85a8

2. [Rule 1 - Bug, waehrend der Arbeit selbst erkannt und korrigiert] Neu ausgeloeste zurueckgestellte Regeln in DropZone.tsx

  • Found during: Teillieferung B, unmittelbar nach dem ersten Entwurf des useSemanticElements-Fixes an DropZone.tsx
  • Issue: Das blosse Entfernen von role="button"/tabIndex/onClick von der Flaechen- <div> (um die Verschachtelung von zwei <button>-Elementen aufzuloesen) liess die verbliebenen onDragOver/onDragLeave/onDrop-Handler auf einer jetzt rollenlosen <div> stehen — das loeste noStaticElementInteractions und noNoninteractiveElementInteractions NEU aus, zwei Regeln, die laut Auftrag bei 5 bzw. 11 unveraendert bleiben mussten.
  • Fix: Struktur korrigiert: die Drop-Flaeche selbst wurde zum <button> (traegt jetzt Klick- UND Drag-Handler), die "Entfernen"-Schaltflaeche liegt als absolut positioniertes Geschwister in der Ecke statt verschachtelt.
  • Files modified: dieselbe Datei wie oben.
  • Verification: Volle Regelmessung nach dem Fix zeigt noStaticElementInteractions=5, noNoninteractiveElementInteractions=11 — unveraendert zum Ausgangswert.
  • Committed in: 21c85a8 (im selben Commit korrigiert, nie mit dem Fehler committet)

Total deviations: 2 auto-fixed (1 blocking type error, 1 selbst erkannte und vor dem Commit korrigierte Regelkollision). Keine der beiden Abweichungen hat den Endstand beeinflusst — beide wurden vor dem jeweiligen Commit vollstaendig geloest.

Vom Plantext abweichende Zuordnung

[Scope-Abweichung] a11y/useSemanticElements (4 Fundstellen) in Teillieferung B bearbeitet, obwohl PLAN.md diese Regel unter D-05 als "erst mit Gestaltungsentscheidung" zurueckgestellt hatte. Der Auftrag fuer diese Sitzung hat die Regel explizit in den 32er-Umfang von Teillieferung B aufgenommen (Zielwert 465 rechnet sie mit ein: 497 − 32 = 465). Bearbeitet wie oben beschrieben — in allen vier Faellen ohne Verhaltenswechsel, nur Tag-/Attributverschiebung. Dokumentiert hier, weil PLAN.md selbst etwas anderes vorsah.

Issues Encountered

Keine ungeloesten Probleme. Die einzige echte Schwierigkeit — die gegenseitige Verschiebung von a11y-Klassifikationen zwischen bearbeiteten und zurueckgestellten Regeln bei DropZone.tsx — ist unter Deviations dokumentiert und vor dem Commit geloest worden.

Known Stubs

Keine. Alle Aenderungen sind vollstaendige, funktionierende Korrekturen; keine Platzhalter, keine leeren Datenquellen.

User Setup Required

None — keine externe Konfiguration erforderlich.

Next Phase Readiness

Der Lint-Rueckstand ist von 2923 auf 465 gesunken und vollstaendig benannt: fuenf zurueckgestellte a11y-Regeln (30 Befunde, D-05), eine bewusst nicht angewendete Regel (noUselessSwitchCase, 1 Befund) und vier gemeldete D-03-Symptomfunde. Empfohlene Folgeaufgaben fuer einen spaeteren Vorgang, in absteigender Dringlichkeit:

  1. force-password-change.interceptor.ts — HTTP-Verfahren tatsaechlich pruefen, sonst unterscheidet die Freigabeliste nicht zwischen Lese- und Schreibzugriff.
  2. change-password/page.tsx — nach erzwungenem Wechsel weiterleiten und Benutzerablage auffrischen.
  3. VehicleTable.tsx — Besetztzustand der Loeschschaltflaeche tatsaechlich anzeigen.
  4. SplitTab.tsx — fest verdrahtete Texte durch den Uebersetzungskatalog ersetzen.
  5. Die fuenf zurueckgestellten a11y-Regeln (30 Befunde) als eigener, mit UI/Design abgestimmter Durchgang.

Kein Blocker fuer laufenden Betrieb: pnpm lint --force bleibt gruen, CI-Tor unveraendert scharf.

Self-Check: PASSED

Alle referenzierten Dateien (biome.json, docs/anleitung-entwicklung.md, diese Summary, DropZone.tsx, calendar-source-form.tsx) auf Datenträger gefunden. Alle referenzierten Commit-Hashes (8d1c8f3, 3811578, 636fe0d, e76f3b8, 4cff316, ae82125, 278aedb, 969fd01, 27a6e29, 73ac08a, 21c85a8, c79bafa, 97a6836) im Verlauf gefunden.


Vorgang: quick-260921-bi2 Abgeschlossen: 2026-09-21