e7c2c4c6a9
Drei Durchgaenge nach Risikoklasse: Konfiguration, maschinelle Fixes plus toter Code, Barrierefreiheit von Hand. Alle Zielzahlen sind beim Planen probeweise ausgefuehrt, gemessen und zurueckgenommen worden. Wichtigster Befund: style/useImportType darf in apps/api nicht maschinell laufen. emitDecoratorMetadata plus NestJS bedeutet, dass die Korrektur 61 von 65 Dateien mit Abhaengigkeitsdaten zerstoert — bei gruenem tsc und gruenen 1124 Tests, weil kein Test den Container startet. Der Plan begrenzt die Regel auf apps/web und verankert als Nachweis einen sha256 ueber die erzeugten __metadata-Zeilen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPPB4ApQxzSU1rwV2Ffj9J
681 lines
46 KiB
Markdown
681 lines
46 KiB
Markdown
---
|
|
phase: quick-260921-bi2
|
|
plan: 01
|
|
type: execute
|
|
wave: 1
|
|
depends_on: []
|
|
files_modified:
|
|
- biome.json
|
|
- docs/anleitung-entwicklung.md
|
|
# Aufgabe 2 — 53 Dateien: 45 maschinell + 11 toter Code, 3 in beiden (gemessen, siehe <verify>)
|
|
- apps/api/src/**
|
|
- apps/api/scripts/rls-scratch-check.mjs
|
|
- apps/web/src/**
|
|
- apps/desktop/src/setup.html
|
|
# Aufgabe 3 — Barrierefreiheit von Hand, 53 Dateien
|
|
- apps/web/src/app/**
|
|
- apps/web/src/components/**
|
|
- apps/web/src/app/icon.svg
|
|
autonomous: true
|
|
requirements: [LINT-BACKLOG]
|
|
|
|
estimate:
|
|
tokens: 205000
|
|
raw_tokens: 205000
|
|
tasks: 3
|
|
confidence: low
|
|
|
|
must_haves:
|
|
truths:
|
|
- "Der Lint-Rueckstand faellt von 2923 auf rund 466 Befunde; kein einziger davon hat die Stufe Fehler, der CI-Schritt Lint bleibt gruen (D-07)."
|
|
- "Die Ausnahme fuer Testdateien greift nachweislich NICHT in echten Quelltext: nach der Konfigurationsaenderung stehen weiterhin exakt 289 noExplicitAny-Befunde in echtem Quelltext, und 0 in Testdateien (D-01)."
|
|
- "Die NestJS-Abhaengigkeitsspritze ueberlebt den maschinellen Durchlauf unversehrt: die aus apps/api erzeugten __metadata-Zeilen sind vor und nach der Aenderung Zeichen fuer Zeichen identisch (593 Zeilen, sha256 6e1583f1...)."
|
|
- "Beide Testlaeufe bleiben punktgleich gruen: apps/api 69 Dateien / 1124 Tests, apps/web 66 Dateien / 459 Tests; pnpm type-check bleibt bei 4/4 (D-07)."
|
|
- "Die Regelgruppe security steht unveraendert auf error — weder im Regelblock noch in einer Ausnahme wird sie erwaehnt (D-06)."
|
|
- "Alle 155 Barrierefreiheits-Befunde der sechs bearbeiteten Regeln sind auf 0; keine a11y-Regel wurde dafuer herabgestuft oder abgeschaltet (D-04, D-06)."
|
|
- "In den drei Formularseiten der Verwaltung ist die Zahl der absendenden Schaltflaechen unveraendert (Mandanten 1, Benutzer 1, LDAP 2) — kein Formular hat seinen Absendeknopf verloren, keine Nebenschaltflaeche loest mehr versehentlich ein Absenden aus."
|
|
- "Es wurde keine repo-weite Formatierung angestossen; der Quelltext-Diff ist zeilenbilanziert (D-08)."
|
|
- "Die Entwickleranleitung nennt den neuen Stand, beide Ausnahmen mit Begruendung und die namentlich aufgefuehrten Folgeaufgaben."
|
|
artifacts:
|
|
- "biome.json — zwei zielgenaue overrides-Eintraege (Testdateien / apps-api) plus die korrigierte Fixture-Ausnahme; security unberuehrt"
|
|
- "docs/anleitung-entwicklung.md — Abschnitt zum Lint-Tor auf den neuen Stand gebracht, beide Ausnahmen begruendet, Folgeaufgaben benannt"
|
|
- "45 Quelldateien mit maschinell erzeugten, danach von Hand gelesenen mechanischen Korrekturen (Aufgabe 2)"
|
|
- "15 Fundstellen toten Codes entfernt bzw. begruendet gemeldet (Aufgabe 2, D-03)"
|
|
- "53 Dateien mit handgeschriebenen Barrierefreiheits-Korrekturen (Aufgabe 3, D-04)"
|
|
- "Ein Abschlussbericht mit Vorher/Nachher-Zahlen, getrennt nach Testdateien und echtem Quelltext, und der Liste dessen, was bewusst stehen bleibt"
|
|
key_links:
|
|
- "biome.json overrides[0].includes -> nur *.spec.ts/*.spec.tsx/*.test.ts/*.test.tsx: die Kette, an der D-01 still zu viel abschalten koennte; Nachweis ist die unveraenderte Zahl 289"
|
|
- "emitDecoratorMetadata (apps/api/tsconfig.json) -> __metadata(design:paramtypes) im erzeugten JS -> Nest loest Abhaengigkeiten auf: die Kette, die ein maschinelles import type in apps/api zerreisst; Nachweis ist der sha256-Vergleich"
|
|
- "biome lint --only=<regel> -> schaltet eine in der Konfiguration abgeschaltete Regel wieder AN: der Grund, warum useImportType pfadgebunden (apps/web packages) und nie repo-weit laufen darf"
|
|
- "<button> ohne Typangabe innerhalb eines <form> -> loest beim Klick ein Absenden aus: die Kette, die useButtonType repariert und die die Zahl der absendenden Schaltflaechen pro Datei belegt"
|
|
---
|
|
|
|
<objective>
|
|
Den Lint-Rueckstand abbauen, den der Vorgang 260921-9ie sichtbar gemacht hat, ohne das Verhalten der
|
|
Anwendung zu veraendern und ohne eine kosmetische Massenumschreibung.
|
|
|
|
Ausgangslage, heute frisch gemessen mit `biome lint . --reporter=json --max-diagnostics=20000`:
|
|
**2923 Befunde, davon 0 auf der Stufe Fehler** — 2067 in Testdateien, 856 in echtem Quelltext.
|
|
|
|
Der Plan geht in drei Durchgaengen vor, geordnet nach Risikoklasse, nicht nach Dateien:
|
|
|
|
| Durchgang | Art der Arbeit | Befunde danach (gesamt / echt / Test) |
|
|
|---|---|---|
|
|
| Start | — | 2923 / 856 / 2067 |
|
|
| 1 — Konfiguration | keine Zeile Quelltext angefasst | 754 / 633 / 121 |
|
|
| 2 — maschinell + toter Code | Werkzeug erzeugt, von Hand gelesen | 621 / 542 / 79 |
|
|
| 3 — Barrierefreiheit | vollstaendig Handarbeit | **466 / 387 / 79** |
|
|
|
|
Alle vier Zeilen sind gemessen, nicht geschaetzt: Durchgang 1 und 2 wurden beim Planen vollstaendig
|
|
probeweise ausgefuehrt, gemessen und danach restlos zurueckgenommen (`git restore .`, Arbeitsbaum
|
|
wieder sauber). Die Zahl fuer Durchgang 3 ist die Differenz der sechs bearbeiteten Regeln.
|
|
|
|
**Zwei Befunde aus der Probe, die den Zuschnitt bestimmen — beide belegt, nicht vermutet:**
|
|
|
|
1. **`style/useImportType` darf in `apps/api` NICHT maschinell angewendet werden.** Es ist mit 224
|
|
Befunden die groesste Einzelregel, 222 davon in `apps/api`. Biome stuft die Korrektur als
|
|
„sicher" ein, sie ist es hier aber nicht: `apps/api/tsconfig.json` hat `emitDecoratorMetadata`
|
|
eingeschaltet, und NestJS loest seine Abhaengigkeiten ueber genau diese erzeugten Daten auf.
|
|
Probelauf an `auth.service.ts`: vorher
|
|
`__metadata("design:paramtypes", [prisma_service_1.PrismaService, ...])`, nachher
|
|
`__metadata("design:paramtypes", [Function, Function, Function, Function, Function, Function])`,
|
|
und die `require`-Zeile des Dienstes verschwindet ersatzlos. Ueber den ganzen Workspace gemessen:
|
|
**61 von 65 Dateien mit Abhaengigkeitsdaten werden beschaedigt.** Die API startet danach nicht
|
|
mehr. Dabei bleibt `pnpm type-check` gruen, und **kein einziger der 1124 API-Tests faellt**, denn
|
|
`grep -rl createTestingModule apps/api/src` liefert 0 Treffer — der Testbestand startet den
|
|
NestJS-Container nirgends. Der Fehler waere also durch jedes bestehende Tor dieses Projekts
|
|
unbemerkt hindurchgegangen. Biome beschreibt das Problem in der eigenen Regelbeschreibung
|
|
(`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. Das ist eine Abweichung von D-02 und
|
|
eine zweite Ausnahme neben D-01 — sie geschieht ausschliesslich, weil D-07 (kein
|
|
Verhaltenswechsel) Vorrang hat, nicht um eine Zahl zu druecken.
|
|
|
|
2. **Nur 4 der 10 in D-02 genannten Regeln haben ueberhaupt eine Korrektur der Klasse „sicher".**
|
|
Probelauf je Regel mit `--write` ohne `--unsafe`: `useImportType`, `noUselessEscapeInRegex`,
|
|
`useConst` und `useExponentiationOperator` aendern etwas; `useNodejsImportProtocol`,
|
|
`useLiteralKeys`, `useOptionalChain`, `useTemplate`, `noUselessSwitchCase` und `useParseIntRadix`
|
|
melden „No fixes applied" und brauchen `--unsafe`. Deren Gesamtdiff ist mit 45 Dateien und rund
|
|
100 Zeilen klein genug, um ihn vollstaendig von Hand zu lesen — was Aufgabe 2 verlangt.
|
|
|
|
Purpose: Das Lint-Tor ist seit dem Vorgang 260921-9ie scharf. Ein Rueckstand von 2923 Warnungen macht
|
|
es blind: eine neue, echte Warnung geht darin unter. Nach diesem Vorgang ist der Rueckstand klein
|
|
genug, um ihn zu ueberblicken, und der Rest ist namentlich benannt statt anonym.
|
|
|
|
Output: Bereinigte `biome.json`, rund 100 bereinigte Quelldateien, aktualisierte Entwickleranleitung,
|
|
ein ehrlicher Abschlussbericht.
|
|
</objective>
|
|
|
|
<execution_context>
|
|
@~/.claude/gsd-core/workflows/execute-plan.md
|
|
@~/.claude/gsd-core/templates/summary.md
|
|
</execution_context>
|
|
|
|
<context>
|
|
@.planning/STATE.md
|
|
@CLAUDE.md
|
|
@biome.json
|
|
@docs/anleitung-entwicklung.md
|
|
|
|
Messbefehl, der in allen drei Aufgaben gebraucht wird — einmal ausfuehren, Ergebnisdatei
|
|
wiederverwenden:
|
|
|
|
```bash
|
|
LJ=$(mktemp /tmp/tessera-lint-XXXXXX.json)
|
|
pnpm exec biome lint . --reporter=json --max-diagnostics=20000 2>/dev/null > "$LJ"
|
|
node -e '
|
|
const d=require(process.argv[1]).diagnostics;
|
|
const T=p=>/\.(spec|test)\.(ts|tsx)$/.test(p);
|
|
const r=d.filter(x=>!T(x.location.path));
|
|
console.log("total",d.length,"| real",r.length,"| test",d.length-r.length,
|
|
"| errors",d.filter(x=>x.severity==="error").length);
|
|
const m={};for(const x of r)m[x.category]=(m[x.category]||0)+1;
|
|
console.log(Object.entries(m).sort((a,b)=>b[1]-a[1]).map(([k,v])=>String(v).padStart(4)+" "+k).join("\n"));
|
|
' "$LJ"
|
|
```
|
|
|
|
Wichtig zur Messung: Der Lauf muss aus dem Wurzelverzeichnis kommen. `pnpm lint` fuehrt
|
|
`biome lint .` je Workspace aus und erreicht `biome.json` selbst nicht; die Grundmessung oben tut es.
|
|
Ausserdem zwischenspeichert Turborepo den Lint-Schritt — fuer die Toraussage `pnpm lint --force`
|
|
verwenden, sonst meldet der Lauf ein altes Ergebnis.
|
|
</context>
|
|
|
|
<tasks>
|
|
|
|
<task type="tracer">
|
|
<name>Aufgabe 1: Konfiguration bereinigen und die Messgrundlage herstellen</name>
|
|
<files>biome.json, docs/anleitung-entwicklung.md</files>
|
|
<precondition>Der Arbeitsbaum ist sauber (`git status --porcelain` liefert nichts). Die drei Durchgaenge bauen aufeinander auf und werden je einzeln festgeschrieben; ein vorbelasteter Baum macht die Diff-Nachweise unlesbar.</precondition>
|
|
<action>
|
|
`biome.json` an drei Stellen aendern, sonst nirgends.
|
|
|
|
(a) **Ausnahme fuer Testdateien (D-01).** Einen `overrides`-Block anlegen, erster Eintrag:
|
|
`includes` auf die vier Muster `**/*.spec.ts`, `**/*.spec.tsx`, `**/*.test.ts`, `**/*.test.tsx`,
|
|
darin `linter.rules.suspicious.noExplicitAny` auf `off`. Diese Muster sind gegen den Bestand
|
|
geprueft: `git ls-files` findet 71 Dateien auf `.spec.ts`, 50 auf `.test.tsx`, 14 auf `.test.ts` und
|
|
keine auf `.spec.tsx`; letzteres Muster bleibt der Symmetrie halber stehen. Weitere Testablagen gibt
|
|
es nicht — keine `__tests__`- und keine `__mocks__`-Verzeichnisse im Bestand.
|
|
|
|
(b) **Ausnahme fuer apps/api (Abweichung von D-02, begruendet in `<objective>` Punkt 1).** Zweiter
|
|
`overrides`-Eintrag: `includes` auf `apps/api/**`, darin `linter.rules.style.useImportType` auf
|
|
`off`. In denselben Eintrag gehoert keine weitere Regel. Der Grund muss als Satz in der
|
|
Entwickleranleitung stehen, nicht nur in der Festschreibung.
|
|
|
|
(c) **Fehlerhafte Fixture-Ausnahme reparieren.** `files.includes` enthaelt heute den Eintrag fuer das
|
|
Fixture-Verzeichnis mit angehaengtem Doppelstern. Biome meldet das selbst als
|
|
`lint/suspicious/useBiomeIgnoreFolder` in `biome.json:11` und nennt die richtige Form in seinem
|
|
Hinweis: seit Version 2.2.0 wird ein Verzeichnis ohne den angehaengten Doppelstern ausgenommen. Den
|
|
Eintrag entsprechend kuerzen. Das betrifft die sechs Dateien unter
|
|
`apps/api/src/tenders/__fixtures__/`.
|
|
|
|
Was NICHT geschieht (D-06): Der Block `linter.rules` wird an keiner anderen Stelle angefasst. Die
|
|
Gruppe `security` kommt in der Datei weder vorher noch nachher vor und erbt damit weiter `error` aus
|
|
`preset: recommended`. Die in 260921-9ie bewusst auf `warn` gesetzten Gruppen bleiben, wie sie sind.
|
|
|
|
Danach `docs/anleitung-entwicklung.md` im Abschnitt zum Lint-Tor (heute rund Zeile 61-69)
|
|
fortschreiben. Der Satz „Aktuell stehen rund 2800 solcher Warnungen offen" ist ab jetzt falsch. Der
|
|
neue Text nennt, in ganzen Saetzen und auf Deutsch: den Stand nach diesem Vorgang; dass `any` in
|
|
Testdateien absichtlich nicht mehr gemeldet wird, weil es dort ausnahmslos an Attrappen haengt und
|
|
eine Umschreibung viel Bewegung bei null Gewinn waere; dass `useImportType` in `apps/api`
|
|
abgeschaltet ist, weil die Korrektur dort die Abhaengigkeitsaufloesung von NestJS zerstoert, Biome
|
|
das in der eigenen Regelbeschreibung einraeumt und der Schaden von keinem Tor dieses Projekts
|
|
bemerkt wuerde; und die Liste dessen, was als eigener Durchgang folgt (siehe Aufgabe 3, Abschnitt
|
|
„Was bewusst stehen bleibt").
|
|
</action>
|
|
<verify>
|
|
<automated>
|
|
# 1. Konfiguration ist gueltiges JSON, hat genau zwei Ausnahmen, und security kommt nicht vor
|
|
node -e '
|
|
const c=require("/home/vicolab/projects/tessera-ctl/biome.json");
|
|
const ok=[];
|
|
ok.push(["overrides-Anzahl", (c.overrides||[]).length===2]);
|
|
ok.push(["Testmuster", JSON.stringify(c.overrides[0].includes)===JSON.stringify(["**/*.spec.ts","**/*.spec.tsx","**/*.test.ts","**/*.test.tsx"])]);
|
|
ok.push(["Testregel", c.overrides[0].linter.rules.suspicious.noExplicitAny==="off"]);
|
|
ok.push(["api-Pfad", JSON.stringify(c.overrides[1].includes)===JSON.stringify(["apps/api/**"])]);
|
|
ok.push(["api-Regel", c.overrides[1].linter.rules.style.useImportType==="off"]);
|
|
ok.push(["security nirgends genannt", !JSON.stringify(c).includes("security")]);
|
|
ok.push(["Fixture-Muster ohne Doppelstern", c.files.includes.includes("!**/__fixtures__")]);
|
|
let bad=0; for(const [n,v] of ok){ if(!v) bad++; console.log((v?"OK ":"FEHL")+" "+n); }
|
|
process.exit(bad);'
|
|
|
|
# 2. Zaehlung: Gesamt 754, echt 633, Test 121, Fehler 0
|
|
LJ=$(mktemp /tmp/tessera-lint-XXXXXX.json)
|
|
pnpm exec biome lint . --reporter=json --max-diagnostics=20000 2>/dev/null > "$LJ"
|
|
node -e '
|
|
const d=require(process.argv[1]).diagnostics;
|
|
const T=p=>/\.(spec|test)\.(ts|tsx)$/.test(p);
|
|
const r=d.filter(x=>!T(x.location.path)).length, t=d.length-r;
|
|
const e=d.filter(x=>x.severity==="error").length;
|
|
const any=d.filter(x=>x.category==="lint/suspicious/noExplicitAny");
|
|
const anyReal=any.filter(x=>!T(x.location.path)).length, anyTest=any.length-anyReal;
|
|
console.log("gesamt",d.length,"echt",r,"test",t,"fehler",e,"| any echt",anyReal,"any test",anyTest);
|
|
const exp=[[d.length,754],[r,633],[t,121],[e,0],[anyReal,289],[anyTest,0]];
|
|
process.exit(exp.filter(([a,b])=>a!==b).length);' "$LJ"
|
|
|
|
# 3. Das Tor bleibt gruen (Turbo-Zwischenspeicher umgehen)
|
|
pnpm lint --force
|
|
pnpm type-check
|
|
</automated>
|
|
</verify>
|
|
<done>
|
|
`biome.json` traegt genau zwei `overrides`-Eintraege und die korrigierte Fixture-Ausnahme; das Wort
|
|
security kommt in der Datei nicht vor. Der Gesamtstand steht bei 754 Befunden (633 echt, 121 Test),
|
|
Fehlerstufe 0. Entscheidend: `noExplicitAny` steht weiterhin bei **exakt 289 in echtem Quelltext**
|
|
und 0 in Testdateien — die Ausnahme reicht nachweislich nicht in den Produktivcode hinein (D-01).
|
|
`pnpm lint --force` meldet 5/5, `pnpm type-check` 4/4. Die Entwickleranleitung nennt den neuen Stand
|
|
und begruendet beide Ausnahmen.
|
|
</done>
|
|
<reversibility rating="reversible">Eine Konfigurationsdatei und ein Dokumentabschnitt; beides ist mit einer Festschreibung zurueckgenommen.</reversibility>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Aufgabe 2: Maschinelle Korrekturen und toter Code</name>
|
|
<files>
|
|
53 Dateien insgesamt. Davon 45 aus dem maschinellen Durchgang in apps/api/src, apps/api/scripts,
|
|
apps/web/src, packages und apps/desktop/src/setup.html — deren genauen Satz bestimmt das Werkzeug,
|
|
<verify> nagelt Anzahl und Zeilenbilanz fest. Namentlich dazu die 11 Fundstellen toten Codes
|
|
(D-03, drei davon stehen schon im maschinellen Satz):
|
|
apps/api/scripts/rls-scratch-check.mjs,
|
|
apps/api/src/auth/decorators/current-user.decorator.ts,
|
|
apps/api/src/auth/interceptors/force-password-change.interceptor.ts,
|
|
apps/api/src/calendar/calendar.service.ts,
|
|
apps/api/src/calendar/dto/create-calendar-source.dto.ts,
|
|
apps/api/src/cert-manager/cert-manager.service.ts,
|
|
apps/api/src/dkv/dkv-parser.service.ts,
|
|
apps/web/src/app/(auth)/login/page.tsx,
|
|
apps/web/src/app/(portal)/change-password/page.tsx,
|
|
apps/web/src/app/(portal)/modules/cert-manager/components/SplitTab.tsx,
|
|
apps/web/src/app/(portal)/modules/dkv-fleet/settings/components/VehicleTable.tsx
|
|
</files>
|
|
<precondition>Aufgabe 1 ist festgeschrieben und der Arbeitsbaum ist wieder sauber. Ohne die Ausnahme fuer `apps/api` aus Aufgabe 1 wuerde der erste Befehl dieses Durchgangs 61 von 65 Dateien mit Abhaengigkeitsdaten beschaedigen.</precondition>
|
|
<action>
|
|
**Erst die beiden Nachweis-Anker setzen, dann anfassen.**
|
|
|
|
Anker 1 — der Ausgangspunkt im Verlauf. `<verify>` misst den Umfang gegen diesen Punkt und nicht
|
|
gegen `HEAD`; sonst faellt die Messung leer aus, sobald die Arbeit festgeschrieben ist, und der
|
|
Umfangsnachweis geht ins Leere:
|
|
|
|
```bash
|
|
BASE=$(git rev-parse HEAD) # Stand nach Aufgabe 1; Wert notieren, in <verify> wiederverwenden
|
|
```
|
|
|
|
Anker 2 — der Abdruck der erzeugten Dekoratordaten. Er ist der eigentliche Beleg dafuer, dass sich
|
|
nichts am Verhalten geaendert hat, und ein gruener Testlauf ersetzt ihn nicht:
|
|
|
|
```bash
|
|
SNAP=$(mktemp -d); pnpm --filter @tessera/api exec tsc --outDir "$SNAP" >/dev/null 2>&1
|
|
grep -rh '__metadata(' "$SNAP" | sort | sha256sum
|
|
# erwartet: 6e1583f1eb72a089eb0ed98f81158b54a9fbd40dbf41371292725f36ef764300 (593 Zeilen)
|
|
```
|
|
|
|
**(A) Durchgang mit gesicherten Korrekturen.** Vier Regeln haben eine Korrektur der Klasse „sicher";
|
|
sie duerfen ohne `--unsafe` laufen:
|
|
|
|
```bash
|
|
pnpm exec biome lint apps/web packages --only=lint/style/useImportType --write
|
|
for R in complexity/noUselessEscapeInRegex style/useConst style/useExponentiationOperator; do
|
|
pnpm exec biome lint . --only="lint/$R" --write --max-diagnostics=20000
|
|
done
|
|
```
|
|
|
|
Die erste Zeile ist **pfadgebunden, und das ist kein Schoenheitsfehler**: `--only=<regel>` schaltet
|
|
eine Regel, die in der Konfiguration auf `off` steht, fuer diesen Lauf wieder AN. Ein repo-weites
|
|
`biome lint . --only=lint/style/useImportType --write` haengt die Ausnahme aus Aufgabe 1 also
|
|
wirkungslos aus und schreibt 201 `import type`-Zeilen nach `apps/api` — beim Planen genau so
|
|
passiert und gemessen. Der Pfad `apps/web packages` ist die einzige zulaessige Form. Betroffen sind
|
|
dort 2 Fundstellen.
|
|
|
|
**(B) Durchgang mit ungesicherten Korrekturen, danach vollstaendig von Hand gelesen.** Sechs Regeln
|
|
haben keine gesicherte Korrektur. Fuenf davon laufen mit `--unsafe`:
|
|
|
|
```bash
|
|
for R in style/useNodejsImportProtocol complexity/useLiteralKeys complexity/useOptionalChain \
|
|
style/useTemplate correctness/useParseIntRadix; do
|
|
pnpm exec biome lint . --only="lint/$R" --write --unsafe --max-diagnostics=20000
|
|
done
|
|
```
|
|
|
|
Danach `git diff` **vollstaendig lesen** — es sind rund 100 Zeilen, das ist zumutbar und verlangt
|
|
(D-02: nie ungeprueft anwenden). Zwei Stellen brauchen dabei ausdruecklich Aufmerksamkeit, weil sie
|
|
in Wegen liegen, die dieses Projekt schon einmal Zeit gekostet haben:
|
|
|
|
- `apps/api/src/ldap/ldap.service.ts` traegt 25 der 31 `useLiteralKeys`-Aenderungen. Es geht um
|
|
Verzeichnis-Merkmale, die heute in eckigen Klammern gelesen werden und danach mit Punkt. Das ist in
|
|
JavaScript dieselbe Operation; die Schreibweise der Merkmalsnamen (`objectGUID`, `sAMAccountName`,
|
|
`cn`, `ou`, `mail`) darf sich dabei an **keiner** Stelle aendern — ein verschluckter Grossbuchstabe
|
|
macht den AD-Abgleich still leer. Zeichenweise gegenlesen.
|
|
- `apps/api/src/auth/strategies/jwt.strategy.ts` und `apps/api/src/auth/auth.service.ts` liegen im
|
|
Anmeldeweg. Dort entstehen Verkuerzungen wie „kein Benutzer oder Benutzer nicht aktiv" zu einer
|
|
einzigen abgesicherten Kette. Pruefen, dass jede dieser Verkuerzungen dieselbe Entscheidung faellt
|
|
wie vorher — insbesondere, dass eine fehlende Sitzung weiterhin zur Abweisung fuehrt und nicht zum
|
|
Durchwinken.
|
|
|
|
**Die sechste Regel wird bewusst NICHT angewendet.** `complexity/noUselessSwitchCase` meldet eine
|
|
Fundstelle in `apps/api/src/tenders/tender-normalizer.service.ts:60`. Die Regel moechte dort eine
|
|
Fallmarke streichen, die unmittelbar ueber einem Kommentar steht, der erklaert, warum der
|
|
Standardzweig genau auf diesem Weg bleiben muss. Die Marke dokumentiert also Absicht, die der Regel
|
|
entgeht. Sie bleibt stehen, wird nicht unterdrueckt und im Abschlussbericht als bewusster Nicht-Fix
|
|
genannt — das ist ehrlicher als eine Unterdrueckung, die wie eine Erledigung aussieht.
|
|
|
|
**(C) Toter Code (D-03), 15 Fundstellen.** Jede einzeln lesen, bevor etwas verschwindet. Drei
|
|
Gruppen:
|
|
|
|
1. *Echt tot, folgenlos entfernbar* — die nicht benutzten Fehlervariablen in
|
|
`calendar.service.ts` (Zeilen 321, 358), `cert-manager.service.ts` (305, 679) und
|
|
`dkv-parser.service.ts` (42): den Namen aus der Auffangklausel streichen, den Rumpf und damit den
|
|
Kontrollfluss unveraendert lassen. Dazu die nicht benutzten Einfuhren in
|
|
`create-calendar-source.dto.ts:2` und die nicht benutzte Funktion `forSystemQuery` in
|
|
`rls-scratch-check.mjs:226` (ein Pruefskript, nicht im Auslieferungsweg).
|
|
2. *Nicht entfernbar, nur umbenennen* — `current-user.decorator.ts:4`: der Wert `data` ist der
|
|
erste von zwei Parametern, die NestJS positionsgebunden uebergibt. Streichen wuerde den zweiten
|
|
verschieben. Stattdessen mit fuehrendem Unterstrich kennzeichnen.
|
|
3. *Symptome, die gemeldet und NICHT stillschweigend repariert werden* — hier ist die unbenutzte
|
|
Variable der Hinweis auf eine echte Luecke, und sie zu schliessen waere ein Verhaltenswechsel, den
|
|
D-07 diesem Vorgang verbietet:
|
|
- `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 entfernen, Luecke im Bericht als Folgeaufgabe nennen.
|
|
- `change-password/page.tsx:11-12` haelt Wegweiser und Benutzerablage vor und benutzt beide
|
|
nicht. Beim Lesen der Datei bestaetigt: nach erfolgreichem Wechsel wird weder weitergeleitet
|
|
noch die Benutzerablage aufgefrischt — bei erzwungenem Wechsel bleibt die Person auf der Seite
|
|
stehen. Die drei Bindungen entfernen, den Befund im Bericht als Folgeaufgabe nennen.
|
|
- `VehicleTable.tsx:164` setzt einen Laufzustand fuers Loeschen, liest ihn aber nie; die
|
|
Loeschschaltflaeche hat also keinen Besetztzustand und laesst sich doppelt ausloesen. Nur die
|
|
lesende Bindung entfernen, die setzende bleibt; Befund im Bericht als Folgeaufgabe nennen.
|
|
- `SplitTab.tsx:20` bekommt die Uebersetzungsfunktion und benutzt sie nicht — ein Hinweis auf
|
|
fest verdrahtete Texte in diesem Reiter. Parameter entfernen, Befund melden.
|
|
- `login/page.tsx:21` haelt einen unbenutzten Wegweiser; hier ist die Weiterleitung
|
|
nachweislich anderswo geloest. Entfernen, keine Meldung noetig.
|
|
|
|
Kein `biome format --write`, auch nicht auf einzelne Dateien (D-08). Der Diff muss zeilenbilanziert
|
|
bleiben.
|
|
</action>
|
|
<verify>
|
|
<automated>
|
|
# 1. STAERKSTER NACHWEIS: die Abhaengigkeitsdaten von NestJS sind Zeichen fuer Zeichen unveraendert.
|
|
# Ein gruener Testlauf kann das NICHT belegen — kein Test dieses Projekts startet den Container
|
|
# (grep -rl createTestingModule apps/api/src liefert 0 Treffer).
|
|
SNAP=$(mktemp -d); pnpm --filter @tessera/api exec tsc --outDir "$SNAP" >/dev/null 2>&1
|
|
test "$(grep -rh '__metadata(' "$SNAP" | wc -l)" = "593" || { echo "FEHL: Zeilenzahl der Dekoratordaten"; exit 1; }
|
|
grep -rh '__metadata(' "$SNAP" | sort | sha256sum \
|
|
| grep -q '^6e1583f1eb72a089eb0ed98f81158b54a9fbd40dbf41371292725f36ef764300' \
|
|
|| { echo "FEHL: Dekoratordaten veraendert — Abhaengigkeitsaufloesung gefaehrdet"; exit 1; }
|
|
echo "OK Dekoratordaten unveraendert (593 Zeilen)"
|
|
|
|
# 2. Umfang festgenagelt: 53 Quelldateien (45 aus dem maschinellen Durchgang + 11 toter Code,
|
|
# davon 3 in beiden), und der Diff hat keinen Zeilenueberschuss (keine Formatierung, D-08).
|
|
# $BASE ist der in <action> notierte Stand nach Aufgabe 1 — gegen HEAD gemessen waere die
|
|
# Pruefung leer und damit wertlos, sobald die Arbeit festgeschrieben ist.
|
|
# git-Ausgabe zuerst einfangen, damit ein Fehlschlag von git nicht in einer Pipe verschwindet.
|
|
test -n "$BASE" || { echo "FEHL: BASE nicht gesetzt (siehe <action>, Anker 1)"; exit 1; }
|
|
CHANGED=$(git diff --name-only "$BASE") || { echo "FEHL: git diff --name-only"; exit 1; }
|
|
N=$(printf '%s\n' "$CHANGED" | grep -v '^\(biome\.json\|docs/\)' | grep -c .)
|
|
test "$N" = "53" || { echo "FEHL: $N statt 53 Quelldateien"; printf '%s\n' "$CHANGED"; exit 1; }
|
|
STAT=$(git diff --numstat "$BASE" -- ':!biome.json' ':!docs') || { echo "FEHL: git diff --numstat"; exit 1; }
|
|
printf '%s\n' "$STAT" | awk '
|
|
{a+=$1;b+=$2}
|
|
END {print "Zugaenge",a,"Abgaenge",b;
|
|
if (a>b) {print "FEHL: Zeilenueberschuss — Formatierung mitgelaufen?"; exit 1}}'
|
|
|
|
# Zwischenprobe, direkt nach Schritt (B) und VOR dem toten Code auszufuehren:
|
|
# MID=$(git diff --name-only "$BASE") ; printf '%s\n' "$MID" | grep -vc '^biome\.json'
|
|
# -> muss 45 ergeben
|
|
|
|
# 3. Die neun bearbeiteten Regeln stehen auf 0, die bewusst stehen gelassene auf 1
|
|
LJ=$(mktemp /tmp/tessera-lint-XXXXXX.json)
|
|
pnpm exec biome lint . --reporter=json --max-diagnostics=20000 2>/dev/null > "$LJ"
|
|
node -e '
|
|
const d=require(process.argv[1]).diagnostics;
|
|
const c=r=>d.filter(x=>x.category==="lint/"+r).length;
|
|
const soll={"style/useImportType":0,"style/useNodejsImportProtocol":0,"complexity/useLiteralKeys":0,
|
|
"complexity/useOptionalChain":0,"style/useTemplate":0,"complexity/noUselessEscapeInRegex":0,
|
|
"style/useConst":0,"style/useExponentiationOperator":0,"correctness/useParseIntRadix":0,
|
|
"correctness/noUnusedVariables":0,"correctness/noUnusedImports":0,
|
|
"correctness/noUnusedFunctionParameters":0,"complexity/noUselessSwitchCase":1};
|
|
let bad=0; for(const [r,s] of Object.entries(soll)){const v=c(r); if(v!==s){bad++;console.log("FEHL",r,v,"statt",s);} }
|
|
const T=p=>/\.(spec|test)\.(ts|tsx)$/.test(p);
|
|
const re=d.filter(x=>!T(x.location.path)).length;
|
|
console.log("gesamt",d.length,"echt",re,"test",d.length-re,"fehler",d.filter(x=>x.severity==="error").length);
|
|
if(d.length!==621||re!==542) {bad++;console.log("FEHL Gesamtstand, erwartet 621/542");}
|
|
if(d.filter(x=>x.severity==="error").length!==0){bad++;console.log("FEHL Fehlerstufe nicht 0");}
|
|
process.exit(bad);' "$LJ"
|
|
|
|
# 4. Unveraenderte gruene Balken
|
|
pnpm --filter @tessera/api run test 2>&1 | grep -q "Test Files 69 passed (69)" || { echo "FEHL api Dateien"; exit 1; }
|
|
pnpm --filter @tessera/api run test 2>&1 | grep -q "Tests 1124 passed (1124)" || { echo "FEHL api Tests"; exit 1; }
|
|
pnpm --filter @tessera/web run test 2>&1 | grep -q "Test Files 66 passed (66)" || { echo "FEHL web Dateien"; exit 1; }
|
|
pnpm --filter @tessera/web run test 2>&1 | grep -q "Tests 459 passed (459)" || { echo "FEHL web Tests"; exit 1; }
|
|
pnpm type-check
|
|
pnpm lint --force
|
|
</automated>
|
|
</verify>
|
|
<done>
|
|
Die erzeugten Dekoratordaten aus `apps/api` sind unveraendert (593 Zeilen, sha256 `6e1583f1...`) — der
|
|
maschinelle Durchgang hat die Abhaengigkeitsaufloesung von NestJS nachweislich nicht angetastet.
|
|
Genau 45 Quelldateien sind geaendert, der Quelltext-Diff ist zeilenbilanziert (keine Formatierung
|
|
mitgelaufen). Die neun bearbeiteten Regeln stehen auf 0, `noUselessSwitchCase` bewusst auf 1. Der
|
|
Gesamtstand liegt bei 621 Befunden (542 echt, 79 Test), Fehlerstufe 0. Beide Testlaeufe sind
|
|
punktgleich gruen (69/1124 und 66/459), `pnpm type-check` 4/4, `pnpm lint --force` 5/5. Die fuenf
|
|
Symptomfunde aus D-03 sind im Bericht namentlich als Folgeaufgaben festgehalten, nicht stillschweigend
|
|
repariert.
|
|
</done>
|
|
<reversibility rating="costly">45 Dateien maschinell veraendert. Zuruecknehmen heisst eine Festschreibung verwerfen — technisch einfach, aber der von Hand gelesene Diff waere noch einmal zu lesen. Deshalb steht der Abdruck der Dekoratordaten VOR der ersten Aenderung.</reversibility>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Aufgabe 3: Barrierefreiheit von Hand</name>
|
|
<files>
|
|
53 Dateien, ueberwiegend apps/web/src/components und apps/web/src/app, dazu
|
|
apps/web/src/app/icon.svg und apps/desktop/src/setup.html.
|
|
Schwerpunkte (Befunde je Datei):
|
|
apps/web/src/app/(portal)/admin/ldap/page.tsx (15),
|
|
apps/web/src/app/(portal)/admin/users/page.tsx (11),
|
|
apps/web/src/components/settings/calendar-settings-panel.tsx (11),
|
|
apps/web/src/components/layout/sidebar.tsx (9),
|
|
apps/web/src/app/(portal)/admin/tenants/page.tsx (8),
|
|
apps/web/src/components/dashboard/widget-catalog-modal.tsx (8),
|
|
apps/web/src/components/layout/header.tsx (8),
|
|
apps/web/src/components/admin/admin-sidebar.tsx (7),
|
|
apps/web/src/components/dashboard/widget-registry.tsx (7)
|
|
</files>
|
|
<precondition>Aufgabe 2 ist festgeschrieben und der Arbeitsbaum ist sauber. Die Zaehlungen in diesem Durchgang gehen vom Stand 621/542/79 aus.</precondition>
|
|
<action>
|
|
Zuerst den Ausgangspunkt im Verlauf festhalten, damit `<verify>` den Umfang messen kann, auch wenn
|
|
die Arbeit zwischendurch festgeschrieben wird:
|
|
|
|
```bash
|
|
BASE3=$(git rev-parse HEAD) # Stand nach Aufgabe 2
|
|
```
|
|
|
|
Hier hilft kein Werkzeug: fuer alle sechs Regeln dieses Durchgangs liefert Biome weder eine
|
|
gesicherte noch eine ungesicherte Korrektur — beim Planen je Regel mit `--write` und mit
|
|
`--write --unsafe` geprueft, Ergebnis jeweils null geaenderte Dateien (einzige Ausnahme
|
|
`noRedundantRoles` mit 3 Dateien unter `--unsafe`). **155 Fundstellen in 53 Dateien, von Hand.**
|
|
|
|
Bearbeitet werden diese sechs Regeln:
|
|
|
|
| Regel | Befunde | Vorgehen |
|
|
|---|---|---|
|
|
| `a11y/noSvgWithoutTitle` | 71 | je Symbol entscheiden |
|
|
| `a11y/useButtonType` | 52 | je Schaltflaeche entscheiden |
|
|
| `a11y/noLabelWithoutControl` | 22 | Beschriftung an Feld binden |
|
|
| `a11y/useAriaPropsSupportedByRole` | 5 | Merkmal oder Rolle richtigstellen |
|
|
| `a11y/noRedundantRoles` | 4 | doppelte Rollenangabe entfernen |
|
|
| `a11y/useAriaPropsForRole` | 1 | fehlendes Pflichtmerkmal ergaenzen |
|
|
|
|
**Symbole (71).** Alle Symbole in diesem Projekt sind eingebettete Grafiken; eine Symbolbibliothek
|
|
gibt es nicht. Je Fundstelle eine von zwei Entscheidungen, und die Entscheidung haengt daran, ob
|
|
daneben schon Text steht:
|
|
- Das Symbol begleitet sichtbaren Text (Menueeintrag mit Beschriftung, Schaltflaeche mit Wort) →
|
|
es ist Schmuck und wird fuer die Vorlesehilfe ausgeblendet. Sonst liest sie die Sache doppelt.
|
|
- Das Symbol steht allein und traegt die ganze Bedeutung (Schliessen-Kreuz, Zahnrad, Lupe ohne
|
|
Wort) → es bekommt einen Titel, der sagt, was die Bedienung tut, nicht wie sie aussieht. Der Text
|
|
gehoert in den Uebersetzungskatalog, wenn die umgebende Datei bereits uebersetzt; sonst als
|
|
deutscher Klartext, passend zum Umfeld.
|
|
Zwei Fundstellen liegen ausserhalb der React-Oberflaeche: `apps/web/src/app/icon.svg` (die
|
|
Bildmarke — Titel mit dem Produktnamen) und `apps/desktop/src/setup.html:173` (Einrichtungsseite des
|
|
Desktop-Programms).
|
|
|
|
**Schaltflaechen (52).** Hier ist die Regel kein Formfehler, sondern deckt echte Fehlbedienung auf:
|
|
eine Schaltflaeche ohne Typangabe innerhalb eines Formulars sendet das Formular ab. Deshalb je
|
|
Fundstelle lesen, was die Schaltflaeche tatsaechlich tun soll, und entsprechend auszeichnen —
|
|
nicht pauschal dasselbe eintragen. Nur drei der 25 betroffenen Dateien enthalten ueberhaupt ein
|
|
Formular:
|
|
- `admin/tenants/page.tsx` — 1 Formular, 6 Fundstellen
|
|
- `admin/users/page.tsx` — 1 Formular, 6 Fundstellen
|
|
- `admin/ldap/page.tsx` — 2 Formulare, 4 Fundstellen
|
|
In diesen drei Dateien ist der Absendeknopf jeweils **schon richtig ausgezeichnet** (gezaehlt:
|
|
1 / 1 / 2). Die 16 Fundstellen dort sind also durchweg Neben-Schaltflaechen — Abbrechen, Schliessen,
|
|
Zeilenaktionen —, die heute beim Klick ungewollt absenden. Sie bekommen die Auszeichnung fuer „tut
|
|
etwas anderes". Damit aendert sich Verhalten, und zwar genau das kaputte: das ist der Zweck der
|
|
Regel und ausdruecklich von D-04 gedeckt. Die Zahl der absendenden Schaltflaechen je Datei muss
|
|
danach unveraendert bei 1 / 1 / 2 stehen — das prueft `<verify>`. In den uebrigen 22 Dateien gibt es
|
|
kein Formular; dort ist die Auszeichnung reine Absicherung.
|
|
|
|
**Beschriftungen (22).** Beschriftung und Eingabefeld ueber eine Kennung verbinden, oder die
|
|
Beschriftung um das Feld legen. Kennungen muessen je Seite eindeutig bleiben — in Listen mit
|
|
wiederholten Zeilen die Zeilenkennung in die Feldkennung aufnehmen. Danach gehoert zu jeder
|
|
Beschriftung genau ein Feld.
|
|
|
|
**Rollen und Merkmale (10).** Die fuenf Merkmale, die zur gesetzten Rolle nicht passen, das eine
|
|
fehlende Pflichtmerkmal und die vier doppelt gesetzten Rollen einzeln richtigstellen. Bei
|
|
`noRedundantRoles` darf der maschinelle Vorschlag als Ausgangspunkt dienen
|
|
(`pnpm exec biome lint apps/web --only=lint/a11y/noRedundantRoles --write --unsafe`, 3 Dateien),
|
|
das Ergebnis ist trotzdem zu lesen.
|
|
|
|
**Was bewusst stehen bleibt (30 Befunde, D-05).** Diese sechs Regeln werden NICHT bearbeitet, weil
|
|
jede eine Gestaltungsentscheidung oder einen Verhaltenswechsel verlangt, den dieser Vorgang nicht
|
|
treffen darf:
|
|
- `noNoninteractiveElementInteractions` (11) und `noStaticElementInteractions` (5) — verlangen die
|
|
Entscheidung, ob aus einem geklickten Bereich eine echte Bedienung wird oder der Klick weg soll.
|
|
- `useKeyWithClickEvents` (5) — verlangt einen Tastaturweg, den es heute nicht gibt; das ist neue
|
|
Bedienung, kein Aufraeumen.
|
|
- `noAutofocus` (4) — das Entfernen verschiebt den Eingabefokus beim Seitenaufruf und ist damit ein
|
|
Verhaltenswechsel, den D-07 hier verbietet.
|
|
- `useSemanticElements` (4) — verlangt einen Austausch von Bauelementen mitsamt Gestaltung.
|
|
- `noNoninteractiveTabindex` (1) — aendert die Tabulatorreihenfolge.
|
|
Diese 30 gehoeren in den Bericht und in die Entwickleranleitung, nicht in eine stille Ablage. Keine
|
|
dieser Regeln wird herabgestuft oder abgeschaltet (D-06).
|
|
|
|
**Abschlussbericht.** Zum Schluss den Vorher/Nachher-Stand festhalten: 2923 → 466, getrennt nach
|
|
echtem Quelltext (856 → 387) und Testdateien (2067 → 79), mit der Aufschluesselung dessen, was
|
|
bleibt, und den in Aufgabe 2 gefundenen Symptomen als benannte Folgeaufgaben. Denselben Stand in
|
|
`docs/anleitung-entwicklung.md` nachziehen, falls die in Aufgabe 1 geschriebene Zahl abweicht.
|
|
</action>
|
|
<verify>
|
|
<automated>
|
|
# 1. Die sechs bearbeiteten Regeln stehen auf 0, die sechs zurueckgestellten unveraendert
|
|
LJ=$(mktemp /tmp/tessera-lint-XXXXXX.json)
|
|
pnpm exec biome lint . --reporter=json --max-diagnostics=20000 2>/dev/null > "$LJ"
|
|
node -e '
|
|
const d=require(process.argv[1]).diagnostics;
|
|
const c=r=>d.filter(x=>x.category==="lint/a11y/"+r).length;
|
|
const erledigt={noSvgWithoutTitle:0,useButtonType:0,noLabelWithoutControl:0,
|
|
useAriaPropsSupportedByRole:0,noRedundantRoles:0,useAriaPropsForRole:0};
|
|
const zurueck={noNoninteractiveElementInteractions:11,noStaticElementInteractions:5,
|
|
useKeyWithClickEvents:5,noAutofocus:4,useSemanticElements:4,noNoninteractiveTabindex:1};
|
|
let bad=0;
|
|
for(const [r,s] of Object.entries(erledigt)) if(c(r)!==s){bad++;console.log("FEHL erledigt",r,c(r),"statt",s);}
|
|
for(const [r,s] of Object.entries(zurueck)) if(c(r)!==s){bad++;console.log("FEHL zurueckgestellt",r,c(r),"statt",s);}
|
|
const T=p=>/\.(spec|test)\.(ts|tsx)$/.test(p);
|
|
const re=d.filter(x=>!T(x.location.path)).length;
|
|
console.log("ENDSTAND gesamt",d.length,"echt",re,"test",d.length-re,
|
|
"fehler",d.filter(x=>x.severity==="error").length);
|
|
if(d.length!==466||re!==387){bad++;console.log("FEHL Endstand, erwartet 466/387");}
|
|
if(d.filter(x=>x.severity==="error").length!==0){bad++;console.log("FEHL Fehlerstufe nicht 0");}
|
|
process.exit(bad);' "$LJ"
|
|
|
|
# 2. Keine a11y-Regel wurde herabgestuft, um diese Zahlen zu erreichen (D-06)
|
|
node -e '
|
|
const c=require("/home/vicolab/projects/tessera-ctl/biome.json");
|
|
const s=JSON.stringify(c.linter.rules.a11y)+JSON.stringify(c.overrides);
|
|
const ok = c.linter.rules.a11y==="warn" && !s.includes("a11y/") && !/"a11y"\s*:\s*\{/.test(JSON.stringify(c.overrides));
|
|
console.log(ok?"OK a11y unveraendert auf warn, keine Einzelausnahme":"FEHL a11y angefasst");
|
|
process.exit(ok?0:1);'
|
|
|
|
# 3. Kein Formular hat seinen Absendeknopf verloren, keine Nebenschaltflaeche sendet mehr ab
|
|
cd /home/vicolab/projects/tessera-ctl
|
|
for f in "apps/web/src/app/(portal)/admin/tenants/page.tsx:1" \
|
|
"apps/web/src/app/(portal)/admin/users/page.tsx:1" \
|
|
"apps/web/src/app/(portal)/admin/ldap/page.tsx:2"; do
|
|
p="${f%:*}"; soll="${f##*:}"
|
|
ist=$(grep -c 'type="submit"' "$p")
|
|
formulare=$(grep -c '<form' "$p")
|
|
test "$ist" = "$soll" && test "$formulare" = "$soll" \
|
|
|| { echo "FEHL $p: $ist absendende Schaltflaechen bei $formulare Formularen, erwartet $soll"; exit 1; }
|
|
echo "OK $p $ist/$formulare"
|
|
done
|
|
|
|
# 4. Der API-Teil ist in diesem Durchgang gar nicht angefasst worden.
|
|
# $BASE3 ist der in <action> notierte Stand nach Aufgabe 2; gegen HEAD gemessen liefe die
|
|
# Pruefung nach dem Festschreiben leer. git-Ausgabe zuerst einfangen — ein Fehlschlag von git
|
|
# saehe sonst aus wie "nichts geaendert".
|
|
test -n "$BASE3" || { echo "FEHL: BASE3 nicht gesetzt (siehe <action>)"; exit 1; }
|
|
API_DIFF=$(git diff --name-only "$BASE3" -- apps/api packages) || { echo "FEHL: git diff"; exit 1; }
|
|
test -z "$API_DIFF" || { echo "FEHL: apps/api oder packages veraendert:"; printf '%s\n' "$API_DIFF"; exit 1; }
|
|
|
|
# 5. Unveraenderte gruene Balken
|
|
pnpm --filter @tessera/web run test 2>&1 | grep -q "Test Files 66 passed (66)" || { echo "FEHL web Dateien"; exit 1; }
|
|
pnpm --filter @tessera/web run test 2>&1 | grep -q "Tests 459 passed (459)" || { echo "FEHL web Tests"; exit 1; }
|
|
pnpm --filter @tessera/api run test 2>&1 | grep -q "Tests 1124 passed (1124)" || { echo "FEHL api Tests"; exit 1; }
|
|
pnpm type-check
|
|
pnpm lint --force
|
|
</automated>
|
|
<human-check>
|
|
Die 52 Schaltflaechen-Aenderungen sind die einzige Stelle dieses Vorgangs, an der sich absichtlich
|
|
Verhalten aendert, und ein gruener Testlauf deckt davon nur einen Teil ab. Darum im Entwicklungsbetrieb
|
|
(`pnpm dev`, nicht gegen den Testserver) die drei Formularseiten der Verwaltung oeffnen — Mandanten,
|
|
Benutzer, LDAP — und je Seite zwei Dinge pruefen: das Formular laesst sich weiterhin ueber seinen
|
|
Absendeknopf abschicken, und ein Klick auf Abbrechen beziehungsweise Schliessen schickt es NICHT ab.
|
|
Nicht ueber Netzwerkaufrufe aus der Seite heraus messen, sondern die Oberflaeche bedienen.
|
|
</human-check>
|
|
</verify>
|
|
<done>
|
|
Die sechs bearbeiteten Barrierefreiheits-Regeln stehen auf 0 (155 Fundstellen in 53 Dateien von Hand
|
|
erledigt), die sechs zurueckgestellten stehen unveraendert bei zusammen 30 und sind im Bericht
|
|
namentlich mit Begruendung aufgefuehrt. Keine a11y-Regel wurde dafuer herabgestuft oder in eine
|
|
Ausnahme gelegt. In den drei Formularseiten steht die Zahl der absendenden Schaltflaechen unveraendert
|
|
bei 1 / 1 / 2, und die Bedienprobe bestaetigt, dass Absenden weiter geht und Abbrechen nicht mehr
|
|
absendet. `apps/api` und `packages` sind in diesem Durchgang unberuehrt. Endstand: **466 Befunde
|
|
(387 echt, 79 Test), Fehlerstufe 0** — von 2923 zu Beginn. Beide Testlaeufe punktgleich gruen,
|
|
`pnpm type-check` 4/4, `pnpm lint --force` 5/5.
|
|
</done>
|
|
<reversibility rating="reversible">Handarbeit an der Oberflaeche, ausschliesslich apps/web und apps/desktop; jede Datei einzeln zuruecknehmbar.</reversibility>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<threat_model>
|
|
## Trust Boundaries
|
|
|
|
| Boundary | Description |
|
|
|----------|-------------|
|
|
| Lint-Konfiguration → CI-Tor | `biome.json` entscheidet, was der CI-Schritt „Lint" ueberhaupt sehen kann. Eine zu weit gefasste Ausnahme blendet echte Befunde dauerhaft aus, ohne dass jemand es bemerkt. |
|
|
| Werkzeug → Quelltext | `biome lint --write` aendert Dateien ohne menschlichen Zwischenschritt, auch in Anmelde-, Sitzungs- und Verzeichnisabgleich-Wegen. |
|
|
| Erzeugtes JS → NestJS-Laufzeit | Die Abhaengigkeitsaufloesung liest Daten, die der Compiler aus Typangaben erzeugt. Kein Tor dieses Projekts prueft diese Daten heute. |
|
|
| Browser → Formular | Eine Schaltflaeche ohne Typangabe loest im Formular ein Absenden aus; ihre Auszeichnung entscheidet, ob ein Klick Daten schreibt. |
|
|
|
|
## STRIDE Threat Register
|
|
|
|
| Threat ID | Category | Component | Severity | Disposition | Mitigation Plan |
|
|
|-----------|----------|-----------|----------|-------------|-----------------|
|
|
| T-bi2-01 | Tampering | `biome.json` overrides[1] (`apps/api/**`, `useImportType` off) | high | mitigate | Nur moeglich, weil die Alternative beweisbar schlimmer ist: 61 von 65 Dateien mit Abhaengigkeitsdaten werden vom maschinellen Fix zerstoert, bei gruenem `tsc` und gruenen 1124 Tests. Begrenzt auf genau eine Regel und einen Pfad; `<verify>` in Aufgabe 1 prueft die Form des Eintrags und dass er keine zweite Regel enthaelt. Begruendung steht schriftlich in der Entwickleranleitung, nicht nur in der Festschreibung. |
|
|
| T-bi2-02 | Tampering | NestJS-Abhaengigkeitsdaten, gesamter maschineller Durchgang | high | mitigate | sha256 ueber alle 593 erzeugten `__metadata`-Zeilen vor und nach dem Durchgang; muss identisch bleiben (`6e1583f1...`). Beim Planen mit dem vollstaendigen Durchgang erprobt: Abdruck blieb identisch. Das ist der einzige Nachweis, der hier traegt — `grep -rl createTestingModule apps/api/src` liefert 0 Treffer, der Testbestand startet den Container nirgends. |
|
|
| T-bi2-03 | Information Disclosure | `biome.json` overrides[0] (Testdateien) | medium | mitigate | Die Ausnahme koennte echten Produktivcode mit abdecken. Geprueft und ausgeschlossen: keine Datei auf `.spec`/`.test` exportiert ein Symbol (`grep -rln "^export" --include=*.spec.ts --include=*.test.ts --include=*.test.tsx` liefert nichts), und keine Datei ausserhalb dieser Muster fuehrt eine solche Datei ein. Laufender Nachweis: `noExplicitAny` bleibt bei exakt 289 in echtem Quelltext — waere die Ausnahme zu weit, faellt diese Zahl. Sie deckt genau eine Regel ab, nicht die Gruppe. |
|
|
| T-bi2-04 | Tampering | `apps/api/src/ldap/ldap.service.ts` (25 `useLiteralKeys`-Aenderungen) | high | mitigate | Der AD-Abgleich liest Verzeichnis-Merkmale ueber ihren Namen; eine verschluckte Grossschreibung macht ihn still leer, und AD ist in diesem Projekt bewusst nur lesend angebunden, also faellt es erst beim Anmelden auf. Diff zeichenweise gegenlesen (in `<action>` verlangt), zusaetzlich `ldap.service.spec.ts` im 1124er-Lauf und `tsc` ueber die getypten Zugriffe. |
|
|
| T-bi2-05 | Elevation of Privilege | `jwt.strategy.ts`, `auth.service.ts` (`useOptionalChain`, `useLiteralKeys`) | high | mitigate | Die Verkuerzungen liegen in Sitzungs-Cookie-Lesung und Aktiv-Pruefung des Kontos. Falsch verkuerzt liesse eine fehlende Sitzung durch. Der Gesamtdiff ist rund 100 Zeilen und wird vollstaendig gelesen; diese beiden Dateien sind in `<action>` namentlich als Lesepflicht markiert. `auth.service.spec.ts` und `jwt.strategy.spec.ts` laufen im 1124er-Bestand mit. |
|
|
| T-bi2-06 | Tampering | Entfernen „unbenutzter" Werte (D-03, 15 Stellen) | medium | mitigate | Ein Wert kann eine Nebenwirkung tragen. Darum drei Gruppen mit unterschiedlicher Behandlung statt eines pauschalen Loeschens: folgenlose Auffangvariablen werden entfernt, der positionsgebundene Dekoratorparameter wird nur umbenannt statt gestrichen, und fuenf Fundstellen sind Symptome echter Luecken und werden gemeldet statt repariert. `<verify>` nagelt den Diff auf 45 Dateien und Zeilenbilanz fest. |
|
|
| T-bi2-07 | Tampering | 52 Schaltflaechen in `apps/web` (`useButtonType`) | medium | mitigate | Eine falsch ausgezeichnete Schaltflaeche kann ein Formular entweder unabsendbar machen oder weiter ungewollt absenden lassen. Nur 3 der 25 Dateien enthalten ueberhaupt ein Formular; dort wird die Zahl der absendenden Schaltflaechen auf 1 / 1 / 2 festgenagelt, und eine Bedienprobe prueft beide Richtungen (Absenden geht, Abbrechen sendet nicht). |
|
|
| T-bi2-08 | Repudiation | Regelgruppe `security`, gesamte Konfiguration | high | mitigate | Der naheliegende Missbrauch dieses Vorgangs waere, Zahlen ueber Herabstufungen zu druecken. Dagegen drei Pruefungen: die Zeichenkette `security` darf in `biome.json` ueberhaupt nicht vorkommen (erbt damit `error` aus dem Vorgabesatz), `linter.rules.a11y` muss unveraendert auf `warn` stehen, und in `overrides` darf keine a11y-Regel auftauchen. Genau zwei Ausnahmen sind zugelassen, beide namentlich in `<verify>` von Aufgabe 1 beschrieben. |
|
|
| T-bi2-09 | Denial of Service | CI-Schritt „Lint" | medium | mitigate | Ein neuer Befund der Stufe Fehler faerbt CI rot. Jede der drei Aufgaben prueft `errors === 0` in der JSON-Zaehlung und laesst zusaetzlich `pnpm lint --force` laufen — mit `--force`, weil Turborepo den Schritt sonst aus dem Zwischenspeicher als gruen meldet. |
|
|
</threat_model>
|
|
|
|
<verification>
|
|
Nach der letzten Aufgabe, aus dem Wurzelverzeichnis:
|
|
|
|
```bash
|
|
LJ=$(mktemp /tmp/tessera-lint-XXXXXX.json)
|
|
pnpm exec biome lint . --reporter=json --max-diagnostics=20000 2>/dev/null > "$LJ"
|
|
node -e '
|
|
const d=require(process.argv[1]).diagnostics;
|
|
const T=p=>/\.(spec|test)\.(ts|tsx)$/.test(p);
|
|
const r=d.filter(x=>!T(x.location.path)).length;
|
|
console.log("gesamt",d.length,"(Start 2923) | echt",r,"(Start 856) | test",d.length-r,"(Start 2067)");
|
|
console.log("fehler",d.filter(x=>x.severity==="error").length,"(muss 0 sein)");
|
|
' "$LJ"
|
|
|
|
SNAP=$(mktemp -d); pnpm --filter @tessera/api exec tsc --outDir "$SNAP" >/dev/null 2>&1
|
|
grep -rh '__metadata(' "$SNAP" | sort | sha256sum # 6e1583f1eb72a089eb0ed98f81158b54a9fbd40dbf41371292725f36ef764300
|
|
|
|
pnpm type-check # 4/4
|
|
pnpm lint --force # 5/5, 0 Fehler
|
|
pnpm --filter @tessera/api run test # 69 Dateien / 1124 Tests
|
|
pnpm --filter @tessera/web run test # 66 Dateien / 459 Tests
|
|
```
|
|
|
|
Zur Ehrlichkeit des Nachweises: Ein gruener Testbestand allein belegt fuer einen maschinellen
|
|
Durchgang ueber 45 Dateien **nicht**, dass sich nichts geaendert hat — dieser Plan hat beim Planen
|
|
einen Fall gemessen, der genau das zeigt (`import type` in `apps/api` laesst `tsc` und alle 1124
|
|
Tests gruen und zerstoert trotzdem den Start der Anwendung). Die tragenden Nachweise sind deshalb,
|
|
in dieser Reihenfolge: der unveraenderte Abdruck der Dekoratordaten, der zeilenbilanzierte und
|
|
vollstaendig von Hand gelesene Diff, die regelweisen Zaehlungen, und erst danach die gruenen
|
|
Testlaeufe.
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
- Lint-Rueckstand von 2923 auf 466 gesenkt (echt 856 → 387, Test 2067 → 79), Fehlerstufe durchgehend 0.
|
|
- `biome.json` traegt genau zwei zielgenaue Ausnahmen; `security` kommt in der Datei nicht vor; keine a11y-Regel herabgestuft.
|
|
- `noExplicitAny` steht nach der Testdatei-Ausnahme unveraendert bei 289 in echtem Quelltext.
|
|
- Die erzeugten NestJS-Dekoratordaten sind Zeichen fuer Zeichen unveraendert (593 Zeilen, sha256 `6e1583f1...`).
|
|
- `pnpm type-check` 4/4, `pnpm lint --force` 5/5, apps/api 69/1124, apps/web 66/459 — alle punktgleich zum Ausgangsstand.
|
|
- Quelltext-Diff zeilenbilanziert; keine repo-weite Formatierung angestossen.
|
|
- Bericht nennt Vorher/Nachher getrennt nach Testdateien und echtem Quelltext, die 30 zurueckgestellten a11y-Befunde mit Begruendung, die fuenf Symptomfunde aus D-03 und die Regeln, die als eigener Durchgang folgen.
|
|
- Entwickleranleitung gibt den neuen Stand und beide Ausnahmen wieder.
|
|
</success_criteria>
|
|
|
|
<output>
|
|
Create `.planning/quick/260921-bi2-lint-rueckstand-abbauen-mechanische-fixe/260921-bi2-SUMMARY.md` when done
|
|
</output>
|
|
</content>
|
|
</invoke>
|