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

440 lines
25 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
phase: quick-260921-bi2
plan: 01
subsystem: tooling
tags: [biome, lint, a11y, nestjs, decorator-metadata, i18n]
requires: []
provides:
- "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"
affects: [ci-lint-gate, apps/web-a11y, apps/api-di]
actuals:
tokens: 37573
tasks: 3
commits: 13
tech-stack:
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."
key-files:
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
key-decisions:
- "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."
requirements-completed: [LINT-BACKLOG]
duration: ~150min (Teillieferung B; Gesamtvorgang laenger, ueber mehrere Sitzungen)
completed: 2026-09-21
status: 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*