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
This commit is contained in:
+439
@@ -0,0 +1,439 @@
|
||||
---
|
||||
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*
|
||||
+111
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user