9.0 KiB
phase, plan, status, subsystem, tags, requires, provides, affects, actuals, tech-stack, key-files
| phase | plan | status | subsystem | tags | requires | provides | affects | actuals | tech-stack | key-files | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| quick-260909-mir | 01 | complete | database |
|
|
|
|
|
|
|
Etappe 2, Bereich dkv — Zusammenfassung
Ergebnis
Alle 21 klassifizierten Zugriffe in apps/api/src/dkv/dkv.service.ts sind
umgestellt. Gebunden sind es am Ende 22 statt 21, weil der neue Besitzriegel vor
dem Ausfuhrdatei-Download einen zusaetzlichen Lesezugriff auf
dkvInvoiceHistory einfuehrt. Genau ein Zugriff bleibt bewusst ungebunden: der
Planer-Startpfad, siehe unten.
Endstand, unabhaengig nachgemessen: 789 Tests gruen (54 Dateien, Ausgangsstand
772/53), Typpruefung 0, rls-scratch-check.mjs 41/41. Schema, Migrationen,
Compose-Dateien und Umgebungsdateien unberuehrt; der Umstellungsschalter bleibt
aus.
Die drei Funde
1. Eine bereits bestehende Fremdzugriffsluecke (T-MIR-03)
DkvService.getExportFile(tenantId, filename) nahm die Mandantenkennung
entgegen und benutzte sie nie. Die Datei wurde allein ueber ihren Namen aus dem
gemeinsamen user-files/-Verzeichnis geholt, abgesichert nur durch einen
Schutz gegen Pfad-Tricks und ein Namensmuster. Ein Administrator eines beliebigen
Mandanten konnte damit die Tankkarten-Auswertung eines anderen herunterladen,
sofern er den Dateinamen kannte.
Der Riegel leitet die Zugehoerigkeit jetzt aus DkvInvoiceHistory.exportFilename
ab — der einzigen mandantengebundenen Aussage darueber, wem eine Ausfuhrdatei
gehoert. Vor dem Umbau wurde in der Oberflaeche geprueft, dass jeder angebotene
Dateiname aus einer Historienzeile stammt (ExportFileList.tsx,
InvoiceHistoryTable.tsx); fuer die regulaere Nutzung aendert der Riegel deshalb
nichts.
Die Luecke ist keine Folge des Umbaus. Sie bestand seit jeher und faellt nur auf, weil dieser Durchlauf jede Zeile des Bereichs einzeln aufschlaegt.
2. Der Bereich hatte keinerlei Tests
Weder eine Attrappe, die nichts prueft (der ldap-Fehler), noch eine fehlende
Attrappe (groups, tenders) — sondern gar keine Testdatei. Jede Zusicherung
dieses Plans waere unpruefbar geblieben. dkv.service.spec.ts wurde deshalb neu
angelegt, mit dem Zwei-Client-Nachweis aus tender-triage.service.spec.ts.
3. Ein zerstoerender Fehler in umgekehrter Richtung
saveConfig enthaelt einen Zweig, der ein bereits gespeichertes Passwort erhalten
soll, wenn der Nutzer das Feld leer laesst. Er verschluckte Lese- und
Entschluesselungsfehler und machte mit den uebergebenen — moeglicherweise leeren —
Werten weiter. Heute faellt das nicht auf, weil der Lesezugriff nie fehlschlaegt.
Nach dem Scharfschalten haette derselbe Zweig ein gespeichertes Passwort durch ein
leeres ersetzt und verschluesselt abgelegt: stiller Verlust, ohne Fehlermeldung,
nicht rekonstruierbar.
Die bewusst getroffene Entscheidung: WINDOWS #21
Der Planer-Startpfad (DkvSchedulerService.onModuleInit →
DkvService.loadAnyActiveConfigForScheduler) bleibt ungebunden. Drei Formen
wurden geprueft:
- (a) an einen konkreten Mandanten binden — nicht moeglich,
onModuleInit()hat beim Start strukturell keinen Mandantenkontext. - (b) Umbau auf einmal-abfragen-viele-bedienen — abgelehnt. Das ist die in Phase 07-04 zurueckgestellte Mehrmandanten-Planung, also eine Funktionsaenderung und kein Bindungsumbau.
- (c) als benannte Altlast weiterfuehren — gewaehlt.
Praezedenzfall ist LdapConfigService.getAllActiveConfigs() aus 260909-ipc, mit
einer Unsymmetrie, die dieser Praezedenzfall NICHT deckt und die deshalb
ausgeschrieben ist: getAllActiveConfigs ist heute korrekt und verstummt erst
nach dem Scharfschalten. Der DKV-Planer ist heute bereits falsch — findFirst()
ohne Bedingung zieht bei mehreren Mandanten einen beliebigen und bedient die
uebrigen nie; ist ausgerechnet die gezogene Zeile inaktiv, bedient er niemanden —
und verstummt zusaetzlich spaeter.
Die Markierung ist dreifach: eine eigens benannte Methode mit Kopfkommentar, der
beide Zustaende nennt (bewusst keine Verzweigung hinter einem optionalen
Parameter, die jemand spaeter "vereinheitlicht"), der fortgeschriebene
Kopfkommentar in dkv-scheduler.service.ts, und der Ledger-Eintrag WINDOWS #21.
Das Signal fuer das Verstummen gehoert in die Vorabpruefung von Etappe 4
(rls-preflight.mjs), nicht in diesen Durchlauf.
Gegenbefunde — geprueft und verworfen
- Kein
$transactionim gesamten Bereich. Die im Kopf vonprisma-tenant.extension.tsgeforderte erneute Pruefung fuer jeden neuen Fall ist damit beantwortet: kein neuer Fall,withTenantTransaction()wird hier nicht gebraucht und wurde nicht eingefuehrt. DkvVehicleMastertraegt@@unique([tenantId, kennzeichen]). Dieser Bereich hat also NICHT dietenders-Falle einer Eindeutigkeitsverletzung auf einer unsichtbaren Zeile. Als Messung festgehalten statt als Absicherung, die nichts absichert.- Die 21 hielt der Pruefung stand. Erster Bereich dieses Vorhabens, dessen Kopfzahl beim Hineinsehen nicht kleiner wurde (zuvor 36→6, 37→34, 62→61, 10→8).
Neu gemessene Form
getHistory fuehrt zwei gebundene Einzelabfragen parallel ueber Promise.all
aus — eine Form, die bisher in keinem Bereich vorkam und die das Werkzeug jetzt
mit einer eigenen Pruefung abdeckt
(dkv-zwei-parallele-gebundene-einzelabfragen-je-eigener-kontext).
Falsifizierungsnachweise
Der Plan verlangt fuer jede Umstellungsaufgabe, dass die Tests durch Rueckbau falsifiziert werden — ein Test, der nicht rot werden kann, beweist nichts. Der Nachweis lag zunaechst nur in einer Commit-Nachricht bzw. gar nicht vor und wird hier nachgetragen, damit er dort steht, wo spaeter jemand nachsieht.
Aufgabe 2 (Konfigurationspfade, Commit 222f453): Der erste gebundene
Client von getConfigForApi wurde probeweise durch this.prisma ersetzt. Genau
Test 1 wurde rot, die sechs uebrigen blieben gruen; der Rueckbau wurde
zurueckgenommen und die Dateiidentitaet zum Ausgangsstand bestaetigt. Belegt in
der Commit-Nachricht von 222f453.
Aufgabe 3 (Historie, Fahrzeugstammdaten, Besitzriegel, Commit 5e8237d):
Der Nachweis fehlte, weil die Ausfuehrung an dieser Stelle durch das
Sitzungslimit abbrach. Er wurde bei der Verifikation nachgeholt: die Bindung des
Besitzriegels wurde zurueckgebaut, worauf genau der benannte Test 10 mit einer
spezifischen Meldung rot wurde, waehrend die sechzehn uebrigen gruen blieben;
danach zurueckgesetzt und der saubere Stand bestaetigt (789/789 Tests,
Typpruefung 0, Werkzeug 41/41).
Beide Nachweise stammen damit aus unterschiedlichen Haenden — Aufgabe 2 vom ausfuehrenden Agenten, Aufgabe 3 vom pruefenden. Das ist kein Nachteil: der zweite Nachweis ist der staerkere, weil ihn jemand erbracht hat, der die Bindung nicht selbst geschrieben hatte.
Ablauf-Hinweis
Die Ausfuehrung wurde am 2026-09-09 gegen Ende von Aufgabe 3 durch ein
Sitzungslimit unterbrochen; die beiden ersten Aufgaben waren committet, die
dritte lag vollstaendig im Arbeitsbaum. Nachgetragen wurden am 2026-09-10 die
Uebersichtstabelle und die Summenzeile im Klassifikationsdokument sowie diese
Zusammenfassung. Die Verifikation fand daran zwei Luecken — der Abschnitt "Der
Hintergrunddienst als Falle" war nicht um den DKV-Planer erweitert worden
(Aufgabe 3 verlangte das ausdruecklich), und die Falsifizierungsnachweise
fehlten in dieser Zusammenfassung; beides wurde danach nachgetragen. Der Bruch fiel auf, weil git status einen nicht leeren
Arbeitsbaum zeigte — nicht, weil ein Bericht ihn gemeldet haette.