- Migration 20260924120000_dashboard_image_drop_data: Schutzpruefung
(bricht ab, solange eine Zeile ohne storagePath existiert; row_security
aus, damit ein Eigentuemer ohne BYPASSRLS nicht still 0 Zeilen sieht),
dann NOT NULL, DROP COLUMN data, DROP POLICY system_read_policy
- Dienst: Bootstrap-Umzug samt forSystem() und Selbstheilung aus data
entfernt; Upload vergibt die UUID selbst, Zeile gleich mit Pfad
- FORSYSTEM_ALLOWED_CALL_SITES, Tests, Zugriffsklassifikation (per
Gate-Schleife gemessen: 61/213/6) nachgezogen
- Betriebshandbuch Kap. 4: Hinweis und Wiederherstellungsweg bei Abbruch
- Todo 2026-09-22 nach completed/
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- FavoriteLink: neue Spalten uploadedIconMime/iconVersion (Migration 20260923160000)
- favorite-icon-files.ts: Erkennung PNG/JPEG/GIF/WebP/ICO/SVG, Pfadbildung ohne
Byte aus der Anfrage im Pfad (T-LRR-01), best-effort Dateientfernung
- FavoritesService: uploadIcon/removeUploadedIcon, Vorrang der hochgeladenen
Datei in getIconBytes, Abrufprobe fuer eine neue iconUrl (422 statt stiller
Speicherung), iconVersion-Erhoehung bei jeder Aenderung der Symbolquelle
- FavoritesController: POST/DELETE /favorites/:id/icon, Cache-Control private
- T-LRR-07 (Restrisiko aus dem Plan-Threat-Model geschlossen, ueber den Plan
hinaus): DashboardService.removeWidget/deleteDashboard raeumen jetzt die
Symboldateien der per Datenbank-Kaskade mitgeloeschten Favoriten auf
(best effort, nie blockierend)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- docs/anleitung-anwender.md: neuer Abschnitt "Proxmox" (Modulzahl vier
auf fuenf korrigiert) — was das Modul zeigt, Server anlegen, NUR-LESE-
Rolle je Produkt, PMG nur Benutzer/Passwort, Zertifikatspruefungs-
Schalter, "Verbindung testen", "unbekannt", D-01 ausdruecklich
festgehalten. Plan nannte "docs/anwenderhandbuch.md" (existiert nicht
im Repo) — echter Dateiname ist docs/anleitung-anwender.md, dort
angewendet (Rule 3, blockierender Pfadfehler)
- docs/anleitung-entwicklung.md: proxmox als Vorlage fuer ein Modul mit
Fremdsystem-Zugaengen und Hintergrundabfrage verlinkt, undici-
Dispatcher-Falle als Merksatz ergaenzt (war noch nicht dokumentiert)
- docs/mandantentrennung-zugriffsklassifikation.md: Bereichsuebersicht
und Summenzeile fuer Aufgabe 5 nachgezogen (war nach Aufgabe 5 noch
offen) — proxmox jetzt 0/11/1, Summe 61/208/7, mit der Gate-Schleife
nachgemessen
Endstand aller Tore gegen die Ausgangswerte des Plans:
- api-Tests: 1311 (Ausgangswert 1240, Ziel >=1240)
- web-Tests: 708 (Ausgangswert 693, Ziel >=693)
- type-check: 4/4
- lint: 5/5
- Biome-Warnungen apps/web: 53 (Ausgangswert 53, exakt unveraendert)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- proxmox-scheduler.service.ts: ein Cron-Auftrag je aktivem Mandant
(proxmox-poll:<tenantId>), onApplicationBootstrap (nicht onModuleInit,
Tender-Muster), Abfrageintervall = kleinstes pollIntervalMin der
aktiven Server, ein fehlgeschlagener Server bricht die Tick-Schleife
nicht ab, refreshTenant() zieht nach jedem Speichern sofort nach
- proxmox.service.ts: loadActiveServersForScheduler() als einziger
forSystem()-Aufruf des Moduls (Erlaubnisliste in
rls-access-inventory.spec.ts), testConnection() schreibt nicht ins
Zwischenlager, pollServer() bekommt eine Zehn-Sekunden-Sperre (T-DHH-06)
- proxmox.controller.ts: POST servers/:id/test, create() zieht den
Planer nach dem Anlegen sofort nach
- Zugriffsklassifikation: proxmoxServer wechselt auf system-gebunden
(Startpfad des Planers), proxmoxServerStatus bleibt gebunden
Tore: api 1306/1306 (>=1240), type-check 4/4, rls-access-inventory
und rls-coverage gruen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
docs/anleitung-anwender.md: neuer Absatz "Mehrere Dashboards (Reiter)" im
Dashboard-Abschnitt, Alltagssprache - mehrere Dashboards nebeneinander,
Ziehen legt den Standard fest, Anlegen/Umbenennen/Loeschen im
Bearbeitungsmodus, der letzte Reiter bleibt.
CHANGELOG.md: ein Stichpunkt unter "Unveroeffentlicht" > "Neu" - was der
Benutzer sieht, mit dem ausdruecklichen Hinweis, dass vorhandene Kacheln
unveraendert auf dem ersten Reiter liegen bleiben.
docs/mandantentrennung-zugriffsklassifikation.md: Endstand nach Task 2
nachgerechnet (nicht aus Task 1 abgeschrieben) - Bereich dashboard 24->28
gebunden (Task 2 bringt vier weitere `tenantPrisma.dashboard.`-Rohtreffer:
createDashboard/renameDashboard/deleteDashboard), Summe 193->197. Die
Begruendungsspalte des Paares dashboard.service.ts/dashboard nennt jetzt
auch Task 2 (withTenantTransaction fuer deleteDashboard/reorderDashboards,
Muster favorites.service.ts/reorder). Paarzahl (75) unveraendert - Task 2
fuegt keine neuen (Datei,Modell)-Paare hinzu, nur weitere Rohtreffer
bestehender Paare.
Alle Tore nachgemessen: api 1240 Tests in 77 Dateien gruen (>= 1202/77),
web 693 Tests in 82 Dateien gruen (>= 661), type-check 4/4, lint 5/5 mit
genau 53 Warnungen in web, `prisma migrate diff` weiterhin ohne Unterschied.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Neues Modell Dashboard (D-01/D-02/D-09): position statt Standard-Feld,
kein Unique auf (userId, position) - Umsortieren schreibt spaeter alle
Positionen einer Transaktion neu. WidgetInstance/DashboardLayout haengen
jetzt am Reiter statt am Benutzer (DashboardLayout.dashboardId @unique
ersetzt userId @unique).
Migration 20260923120000_dashboard_tabs: Zeilenschutz mit Mandant- UND
Benutzerdimension (Form 20260911120000/20260921120000), Bestands-
uebernahme fuer jeden Benutzer mit Kacheln oder Anordnung VOR den
Fremdschluesseln (D-03) - gemessen: 0 Kacheln/Anordnungen ohne Reiter,
genau 2 Reiter auf Position 0.
dashboard.service.ts: listDashboards() (Transaktionssperre gegen
doppelte Erstanlage, T-AD9-07), Riegel assertOwnedDashboard() (fail-
closed gegen fremde Reiter, T-AD9-01/02/03) - getLayout/saveLayout/
getWidgets/addWidget laufen jetzt ueber dashboardId statt userId.
GET /dashboard/tabs neu; die vier bestehenden Wege reichen die Reiter-
Kennung durch. Verhalten fuer den Benutzer unveraendert (ein Reiter,
wie bisher) - Task 2 ergaenzt Anlegen/Umbenennen/Loeschen/Umsortieren.
dashboard.service.spec.ts: 43 Tests (31 alte unveraendert + 12 neue fuer
Reiter-Anlage, -Reihenfolge und den Fremdreiter-Riegel bei allen vier
Wegen). Zugriffsklassifikation nachgerechnet: 75 Paare (+1), Bereich
dashboard 21->24 gebunden.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- eine Kachel ohne Bauteil (entfernter Typ oder gesperrtes Modul) zeigt
statt des rohen Typnamens den Satz `widgets.unavailable`, zentriert und
grau; Schluessel in de.json und en.json
- Entwicklerdoku: neuer Abschnitt "Eine Kachel zum Modul" im
Modul-Walkthrough — die drei verbliebenen Stellen und was eine Kachel
mit moduleSlug automatisch tut
- Changelog unter "Unveroeffentlicht - Geaendert"
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Changelog unter Unveroeffentlicht -> Geaendert: Bilder liegen im
Dateibereich, vorhandene ziehen beim ersten Start automatisch um
- Betriebsanleitung Kap. 6: user-files nennt die Bilderrahmen-Bilder und
haelt fest, dass pg_dump allein sie nicht mehr enthaelt
- Todo fuer Stufe 2 (DROP data, storagePath NOT NULL) mit Vorbedingung,
Migrationsname und den Nacharbeiten an Spec und Klassifikation
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Bytes liegen unter user-files/dashboard-images/<userId>/<id>.<ext>, die
Zeile haelt nur noch storagePath (Muster User.avatarPath)
- Dateiname immer servergeneriert: UUID der Zeile + Endung aus dem
ERKANNTEN Mime-Typ, originalName kommt in keinem Pfad vor (T-HK4-01)
- Migration 20260922120000: storagePath dazu, data wird NULLbar, kein DROP
(zweistufig, T-HK4-03); system_read_policy fuer den Umzug
- onApplicationBootstrap zieht Altbestand automatisch um: systemgebunden
lesen, je Zeile mandantengebunden schreiben (Muster DKV-Planer)
- Upload nimmt die Zeile bei fehlgeschlagenem Schreiben zurueck, Loeschen
entfernt die Datei mit, fehlende Datei -> 404 (T-HK4-04)
- 11 neue Dienst-Tests gegen ein echtes Temp-Verzeichnis (kein fs-Mock)
- Zugriffsklassifikation: Stand system-gebunden, Zahlen nachgemessen
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Changelog: Stichpunkt direkt nach dem XFrame-Stichpunkt unter Unveroeffentlicht -> Neu
- Anwenderhandbuch: je ein Satz in der Widget-Tabellenzeile und im Absatz "Dashboard > Widgets"
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- CHANGELOG: Stichpunkt als erster unter "Unveroeffentlicht -> Neu"
- Anwenderhandbuch: Zeile in der Widget-Tabelle, erweiterter Satz zu den
Widget-Einstellungen, Absatz-Zusatz unter "Dashboard > Widgets"
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- CHANGELOG.md: erster Stichpunkt unter Unveroeffentlicht -> Neu
- docs/anleitung-anwender.md: Zeile in der Widget-Tabelle, Absatz zur
Bildverwaltung unter Dashboard > Widgets
- umlaut-dictionary.ts: „Webadresse“ und „Bildausschnitt“ als korrektes
Deutsch auf die Erlaubnisliste des Umlaut-Waechters (der volle Web-Testlauf
hatte die beiden neuen ss-Woerter aus de.json gemeldet)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Prisma-Modell DashboardImage (bytea) mit Migration 20260921120000: Tabelle,
Indizes, RLS ENABLE/FORCE und tenant_isolation_policy mit Benutzerdimension
- dashboard-image-rules.ts: detectImageMime ueber Magic Bytes (PNG/JPEG/GIF/
WebP), Grenzen 5 MiB je Datei und 30 je Benutzer
- DashboardImagesService: list/upload/getBytes/remove, je Methode
forTenant(prisma, tenantId, userId); Besitz = Mandant UND Benutzer, sonst 404
- DashboardImagesController unter dashboard/images: GET, POST (FileInterceptor
image, 5 MiB, eine Datei), GET :id mit Content-Type aus dem erkannten Typ,
Cache-Control private, nosniff, Content-Disposition inline ohne Dateinamen,
CSP sandbox; DELETE :id
- CreateWidgetDto kennt 'picture-frame'
- Klassifikationsdokument: neues Paar dashboard-images.service.ts/
dashboardImage; Bereichs- und Summenzeilen nachgemessen (dashboard 12->18,
settings 3->4 und bug-reports waren in der Summe nie mitgezaehlt)
- Befund: Prisma-Bytes verlangt Uint8Array<ArrayBuffer>, multers Buffer wird
ohne Zusicherung abgelehnt - Kopie per new Uint8Array(buffer) statt Cast
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Der Lint-Abschnitt trug noch den Zwischenstand aus Aufgabe 1 (754/633/121).
Jetzt der tatsaechliche Endstand nach allen drei Aufgaben, beide Ausnahmen
weiterhin begruendet, plus die namentlich benannten Folgeaufgaben: fuenf
zurueckgestellte a11y-Regeln, die bewusst nicht angewendete
noUselessSwitchCase-Fundstelle, und die vier gemeldeten D-03-Symptomfunde.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TPPB4ApQxzSU1rwV2Ffj9J
- pnpm lint prueft seit #35 echt (biome lint . je Workspace), CI-Schritt Lint blockiert entsprechend
- Fehler stoppen den Lauf, Stilhinweise laufen als Warnungen mit (rund 2800 offen: any-Familie, Barrierefreiheit apps/web) — bewusst eigener Durchlauf, nicht Teil dieses Vorgangs
- Klargestellt: pnpm lint formatiert nicht, dafuer separat biome format --write von Hand
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TPPB4ApQxzSU1rwV2Ffj9J
Damit Betreiber im Postfach sofort erkennen, ob eine Meldung aus einem
Browser oder der Desktop-App kommt (und mit welchem Stand), beschreiben
Administrationshandbuch und Betriebshandbuch das neue Betreff-Kürzel und
die Zeile "Herkunft"; das Betriebshandbuch erklaert zusaetzlich den Fall
eines alten Desktop-Clients ohne Details.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016g2npLxzH5gZpg8s2S6vKh
- Anwenderhandbuch: Menüeintrag "Update installieren", Ablauf per Klick
unter Windows/Linux, Fehlerfall, https-Bedingung, einmaliger Wechsel für
Clients bis 1.2.0
- Betriebshandbuch Kap. 10: Signierschlüssel (Secrets, Ablage, Sicherung,
Verlust), Kontrollzeile /desktop/update, Manifest-Felder, zwei Fehlerbilder
- Entwicklungshandbuch: lokal `tauri build --no-sign`, Hinweise zu tauri dev
- ci-cd-setup.md: die zwei neuen Secrets, Bau-Schritte signieren,
Fehlerbild "no private key"
- CHANGELOG: eine Zeile unter Unveröffentlicht → Neu
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Neuer Unterabschnitt „Server-Adresse ändern" vor „Automatischer Start": wo die Adresse steht (Hinweistext, Menüzeile, Einstellungen → Desktop-App) und wie sie geändert wird (Rechtsklick → „Server-Adresse ändern…" → Setup-Seite → „Verbinden"/„Abbrechen")
- Tray-Liste ergänzt um „Verbunden mit …" (erste Zeile) und „Server-Adresse ändern…"; Hinweis auf den Tooltip nach der Liste; Erststart-Absatz verlinkt den neuen Unterabschnitt
- CHANGELOG.md: zwei Desktop-App-Stichpunkte unter Unveröffentlicht / Neu angehängt, fremde Zeilen unverändert (per git diff gegengeprüft)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- CHANGELOG.md: je ein Stichpunkt unter Neu (Sortierpfeile) und Behoben
(Symbol trotz Zertifikatsfehler/interner Adresse)
- docs/anleitung-anwender.md: Tabellenzeile „Favoriten" nennt die Pfeile
und den Browser-Ersatzweg fuer das Symbol
- docs/mandantentrennung-zugriffsklassifikation.md: Nachtrag zu
favoriteLink — reorder() laeuft ueber withTenantTransaction() ohne
Benutzerdimension in der Sitzung, Stand bleibt gebunden
- prisma-tenant.extension.ts: Kopfkommentar-Nachtrag, favorites.service.ts
(reorder) ist der erste Nutzer-CRUD-Aufrufer von withTenantTransaction()
— nur Kommentartext, Funktionscode unveraendert (prisma-tenant.extension.spec.ts
und rls-access-inventory.spec.ts weiterhin gruen)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- anleitung-betrieb.md Kap. 10: neuer Unterabschnitt "Wann gebaut wird und
wann Pakete uebernommen werden", Job-Dauer-Satz und Fehlerbilder-Tabelle
ergaenzt
- ci-cd-setup.md Abschnitt 4: Absatz zum Ueberspringen bei unveraendertem
Desktop; Abschnitt 6: neuer Fehlerbehebungs-Eintrag
- anleitung-entwicklung.md: Absatz zum CI-Ueberspringen bei "Desktop-App
lokal bauen"
- CHANGELOG.md: ein Stichpunkt unter Unveroeffentlicht/Geaendert
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
publish-release.sh ignoriert GITHUB_API_URL/GITHUB_SERVER_URL (git.vicolab.de
hinter dem Proxy bricht grosse Uploads ab -- Release 1.2.0 blieb dadurch
zunaechst ohne Anhaenge). Im CI wird das Host-Gateway des Job-Containers aus
/proc/net/route ermittelt und Gitea direkt auf Port 3002 angesprochen, lokal
localhost:3002; GITEA_API bleibt als Override. Gateway-Weg aus Job-Netz
gegen die Gitea-API verifiziert; Anhaenge fuer v1.2.0 vom Host nachgetragen.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- bundle.windows.nsis in tauri.conf.json: Deutsch ohne Sprachauswahl,
Tessera-Icon, Kopf-/Seitenbild, currentUser (kein Admin noetig)
- icons/nsis-header.bmp (150x57), icons/nsis-sidebar.bmp (164x314) ergaenzt
- CHANGELOG: vier neue Desktop-App-Stichpunkte (Beta-Hinweis, Installer,
Download-Links, Kontextmenue)
- anleitung-anwender.md: Installationsassistent-Satz, Tray-Eintrag erklaert
- anleitung-entwicklung.md: Ort der nsis-Konfiguration, Pruefweg per CI
- Schema-Pruefung (node) und cargo check gruen
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Bedienprobe des Users: Installer und Start liefen, dann schwarzes Fenster
"asset not found: index.html". Das Fenster "main" hatte keine Startseite,
Tauri nimmt dann index.html; die Erststart-Seite heisst setup.html (Altlast
aus Phase 6, in keinem echten Paket sichtbar geworden). CARGO_BUILD_JOBS=4,
weil 8 parallele rustc-Prozesse den gemeinsam genutzten Runner-Host (15 GB)
an die Speichergrenze brachten; Betriebshandbuch Kap. 10 ergaenzt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Betriebshandbuch: neues Kapitel 10 (Pipeline-Herkunft, Ablageort im Abbild,
Release-Anhaenge, DESKTOP_DIST_DIR, Fehlerbilder-Tabelle); Kapitel 9 um
Satz zu Desktop-Paketen im Freigabe-Tag ergaenzt
- CI/CD-Runbook: aus drei werden vier Jobs, Job desktop ausfuehrlich
beschrieben (Cross-Bau, Cache-Reihenfolge, Cache-vs-upload-artifact-
Begruendung), Fehlerbehebung um drei Unterabschnitte ergaenzt
(Job desktop, cache miss, Release-Upload 413)
- Entwicklungshandbuch: apps/desktop ist kein Grundgeruest mehr, neuer
Abschnitt "Desktop-App lokal bauen", Testabschnitt um vitest src/desktop
und cargo check/clippy ergaenzt
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Neues Kapitel "Desktop-App" (9 Unterabschnitte: Was es ist, Herunterladen,
Installation Windows/Linux, Erster Start, Infobereich/Beenden, Automatischer
Start, Neue Version, Fehlerbilder), Inhaltsverzeichnis um Punkt 8 ergaenzt
- CHANGELOG-Stichpunkt unter Unveroeffentlicht/Neu im Wortlaut von D-17
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Betrieb Kapitel 9: Vorschritt CHANGELOG.md vor dem Tag, automatischer Gitea-Release samt Verhalten bei fehlendem Abschnitt, Erstfreigabe v1.0.0 in der Vergangenheit, vierter Erkennungsweg "Was ist neu"
- Anwender: Satz zur Versionszeile in "Aufbau der Oberflaeche", neuer Abschnitt "Was ist neu" vor den Stolpersteinen, Inhaltsverzeichnis; Abschnitt "Dashboard" (dyv) unangetastet
- Entwicklung: Regel "Aenderungsliste" unter Konventionen und Fallstricke (Bauzeit-Einbettung, Importdisziplin, Kanalregel, Release-Skript)
- CI-Setup (ASCII): REGISTRY_TOKEN mit repository: write, vier Schritte im Job publish, Release je Tag, API-Basis im Job-Container
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
- Abschnitt Dashboard: Stift-Schalter unten rechts, Haekchen "Aenderungen
speichern" und "Widget hinzufuegen" daneben
- Ziehen an beliebiger Stelle der Kachel (Eingabefelder, Knoepfe, Links
ausgenommen), grauer Griff am oberen Rand, Ablegen nur auf freiem Platz
- Mindestgroesse = gerade noch bedienbar; Entfernen-Symbol rechts im Griff
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
- Bearbeitungs-Hinweis: Position und Groesse rasten in feinen Schritten ein
- Uhr-Zeile: Uhrzeit waechst mit der Kachel, feste Schriftgroesse in Punkt unter Einstellungen > Dashboard
- Satz zu den Widget-Einstellungen nennt die Uhr (Zeitzone und Schriftgroesse)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
- Anwender: neuer Abschnitt 8 mit Ablauf, Datenschutz-Hinweis (Bild zeigt die aktuelle Seite), was mitgeschickt wird, Rueckmeldungen; Kopfleiste nennt drei Bedienelemente; Stolperstein "kein Postfach"
- Administration: Kapitel 6 SMTP beschreibt das Feld Fehlermeldungen an (Drossel, 4 MB, Rueckfall, Datenschutz); zwei neue Zeilen in der Fehlersuche-Tabelle
- Betrieb: TESSERA_BUGREPORT_TO in der Konfigurationstabelle (Serverdatei von Hand ergaenzen, wie IMAGE_TAG) und in der Symptomtabelle
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
- anleitung-betrieb.md: neues Kapitel 9 (Kanal, IMAGE_TAG je Server, Freigabe,
Hotfix-Ablauf mit Regel "Keine Datenbankaenderung als Hotfix", drei Kontrollwege,
Einrichtung des Live-Servers, Erstfreigabe v1.0.0); Inhaltsverzeichnis, Tabelle in
Kapitel 1, IMAGE_TAG in Kapitel 3, Etiketten in Kapitel 4, Startzeile in Kapitel 7
- ci-cd-setup.md: REGISTRY_TOKEN und Push ueber localhost:3002, Trigger main/live/v*,
Jobs quality -> test -> publish, Etiketten- und Build-Arg-Tabellen, D-13 ueberholt,
Tag-/Branch-Schutz-Empfehlung (T-KU1-04), Fehlerbehebung fuer den Stempel
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
- Kritikschrift: neuer Abschnitt "## Systemkontext (Etappe 3c, 260914-eym)"
mit (y1) woertlicher Werkzeugausgabe und pg_policies der lebenden DB,
(y2) Signaltabelle beider Fehlerrichtungen samt Rueckbau-Belegen (a)-(d),
(y3) Leere-als-Abwesenheit je Pfad (kein Pfad loescht), (y4) bewusst
nicht geloest, (y5) bewusst nicht angefasst; Nachtraege in (d4), (s4),
(b4) und im Abschluss
- Klassifikation: Uebersichtstabelle mit dritter Spalte System, Werte
nachgerechnet (61/179/5), Stand-Absatz 260914-eym (72 Paare, Klassen
unveraendert, sieben Staende geaendert), sechs Regelschluesse im
Hintergrunddienst-Abschnitt, admin-seed-Zeile mit 3c-Befund, 3c-Punkt
unter "NICHT entscheidet" erledigt
- Auftrag: 3c als Erledigt vermerkt (3d64567/6e2a641), zwei neue Fallen
unter "Werkzeuge und Fallen"
- Datenbankrolle: dritte Sitzungsvariable, Nachtrag zum Systemkontext und
zur weiterhin gueltigen Vorher-Pruefung ohne-kontext-leer
- Ledger (ueber gsd-tools windows): #21 fixed, #30 fixed, #37 neu
(prozessweiter Single-Flight-Riegel processInbox) — open 15 / waived 1 /
fixed 21 / total 37, aus den Zeilen gezaehlt
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
- Neuer Abschnitt "Regelschluss Benutzerdimension (Etappe 3b, 260911-nke)"
in der Kritikschrift mit b1 (woertliche Werkzeugausgabe + pg_policies-Liste),
b2 (Signaltabelle beide Fehlerrichtungen), b3 (NotFound-statt-Forbidden
je Methode), b4/b5 (bewusst nicht geloest/angefasst). Zehn datierte
Nachtraege an allen Stellen, die zuvor "keine Benutzerdimension" als
Stand beschrieben (t1/t4/r4/w1/w4/k1/k4/f1/f4/Abschluss) — historische
Messung bleibt lesbar.
- Klassifikation: drei Bestandsaufnahme-Zeilen (calendarSource,
widgetInstance, favoriteLink) mit Zusatz "Benutzerdimension seit
20260911120000 (260911-nke)"; neuer Punkt "Aufgelöst (260911-nke)" im
Abschnitt "Was diese Etappe NICHT entscheidet"; neuer Stand-Absatz —
Paarzahl (72) und Klassen-Verteilung bleiben unveraendert.
- Betriebsanleitung: `forTenant(prisma, tenantId, userId?)` und die zehn/
vier-Tabellen-Aufteilung nachgezogen.
- Datenbankrolle: neuer Absatz zu `app.current_user`/`current_user_id()`
neben `app.current_tenant`; SECURITY-DEFINER-Kopfkommentare unangetastet.
- Auftrag: 3b als erledigt markiert (Migrationsname, sechs statt drei
Umkehrungen, Endzahlen); 3a/3c unveraendert.
- WINDOWS.md: neuer Eintrag #34 (open, deviation) fuer die bewusst offene
Flanke — Aufrufer ohne userId sieht den ganzen Mandanten, kein Waechter
gebaut.
- Baseline: 1020/62 Tests, Typpruefung sauber, Werkzeug 203/203 bestanden.
Erlaubnisliste gegen 8829999 eingehalten, schema.prisma/Compose/.env/3a
unveraendert.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AMASaSxv5QMY7RncqZriRR
- Klassifikationsdokument: Klassen-Verteilung (35/21/14/2, 72 Paare),
Uebersichtsabsatz (zweite methodische Luecke, geschlossen) und
Hintergrunddienst-Nachtrag (ldap/getAllActiveConfigs reicht auch in
LdapFieldMapping hinein) aus Tabelle/Greps abgeleitet, nicht abgeschrieben
- Kritikschrift: Nachtrag (260911-mkj) unter (n4) im Bereich tenant, Vermerk
im Etappe-2-Abschluss dass #27 geschlossen ist
- WINDOWS.md: #27 fixed (Nachweis: vierte Erkennungsform, Proben,
Zwischenmessung 7/3/1); neuer Eintrag #33 fuer die Empfaenger ausserhalb
der vier Erkennungsformen (tenders.seed.ts, backfill-tender-source.ts)
- Spec: WINDOWS #TBD-MKJ-Platzhalter durch #33 ersetzt
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AMASaSxv5QMY7RncqZriRR
- rls-access-inventory.spec.ts: analyzeFile in analyzeSource(source, relPath)
herausgeloest, parseSchemaRelations() liest schema.prisma zur Testzeit,
vierte Erkennung loest include:/select:/_count:/Relationsfilter ueber
SCHEMA_RELATIONS auf das Zielmodell auf und traegt es als eigene
Fundstelle (gebunden/ungebunden nach Empfaenger) ein
- drei Waechter (Rohzahl vs. erkannte Modellaufrufe, Stale-Check fuer
RELATION_SPEC_EXCEPTIONS, unresolvedRelationSpecValues leer), zwei
Schema-Tests, acht gepinnte Proben (WINDOWS #27 ungebunden/gebunden,
reale ldap-Form, verschachtelte where-Kette, Negativprobe, _count: true,
unbekannter Empfaenger, Konstantenaufloesung)
- Bestandsaufnahme (docs/mandantentrennung-zugriffsklassifikation.md): sieben
neue Paare, drei fortgeschriebene Staende (davon ldapFieldMapping mit
Klassenwechsel auf beides), Kopfabsatz "Erkennungsluecke GESCHLOSSEN"
ersetzt den alten "seit 260911-e2s vermessen"-Absatz, 65 -> 72 Paare
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AMASaSxv5QMY7RncqZriRR
- .planning/WINDOWS.md: drei neue offene Eintraege (#30 Startpfad des
Mailmoduls, #31 verschluckte Leere favorites, #32 verschluckte Leere
settings); Platzhalter WINDOWS #TBD-GWH in settings.service.ts und
mail.module.ts durch #30 ersetzt
- docs/mandantentrennung-zugriffsklassifikation.md: Uebersichtszeilen
favorites (0/8, war 7/0) und settings (1/3, war 4/0) neu gemessen;
Summenzeile 68/178 (Endstand Etappe 2); Bestandsaufnahme (favoriteLink
gebunden, smtpConfig gemischt, neue Zeile widgetInstance/gebunden);
Klassen-Verteilung 65 Paare (33/17/13/2); Hintergrunddienst-Abschnitt mit
sechstem Fall (mail.module.ts, WINDOWS #30) und erfuellter
Befund-K-Bedingung; neuer Punkt in "Was diese Etappe NICHT entscheidet"
- docs/mandantentrennung-etappe2-fehlerrichtung.md: Nachtraege unter Befund
K in (t4) und im Uebergaben-Absatz von (d4) -- Reihenfolgebedingung
erfuellt; ## Etappe 2 -- Abschluss mit den derivierten Endzahlen
- docs/anleitung-entwicklung.md: 23 RLS-Tabellen statt sieben, FavoriteLink
nicht mehr als Tabelle ohne Regel, tenantPrisma statt manuellem
tenantId-Filter als gelebter Stil
- rls-access-inventory.spec.ts wieder gruen (11/11), volle Suite 994/994,
Werkzeug 137/137; zwei Dokument-Falsifizierungen durchgefuehrt und
zurueckgenommen (siehe SUMMARY)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AMASaSxv5QMY7RncqZriRR
- runFavoritesAreaChecks (8 Pruefungen) und runSettingsAreaChecks (9 Pruefungen)
erweitern rls-scratch-check.mjs auf 137 bestandene Pruefungen
- FavoriteLink-Wegwerftabelle traegt den Fremdschluessel auf WidgetInstance
(Befund C, WINDOWS #27), SmtpConfig-Wegwerftabelle den Eindeutigkeitsindex
- Ergebnis Pruefung 7: der Fremdschluessel prueft am Zeilenschutz vorbei
(steuert den Besitzriegel in Aufgabe 2); Pruefung 8: ungebundenes upsert
wirft PrismaClientUnknownRequestError, dieselbe Klasse wie 260910-krx
- docs/mandantentrennung-etappe2-fehlerrichtung.md: Abschnitte
## Bereich favorites (f1-f5), ## Bereich settings (s1-s5) und
## Etappe 2 -- Abschluss; Nachtraege unter Befund K in (t4) und im
Uebergaben-Absatz von (d4) -- die Reihenfolgebedingung ist erfuellt
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AMASaSxv5QMY7RncqZriRR
- auth.controller.spec.ts: NEU. Mandantenquelle je Handler (das Claim fuer
me/changePassword; fuer die oberste Rolle der Mandant des Ziels aus dem
Fan-out), unbekanntes Ziel, null-Durchreichung von me, Rollen-Metadaten
(ROLES_KEY) und Public-Metadaten (IS_PUBLIC_KEY) fuer alle sieben
Handler — 23 Faelle; Falsifizierungsnachweis am Fan-out-Zweig
durchgefuehrt und zurueckgenommen
- docs/mandantentrennung-zugriffsklassifikation.md: Uebersichtszeile auth
auf 3/10 (war 8/5), Summenzeile 78/167, Bestandsaufnahme-Zeile
auth.service.ts/user auf gebunden (keine gemischt-Zeile mehr fuer diese
Datei), Klassen-Verteilung unveraendert bei 64 Paaren mit
Stand-Vermerk, Hintergrunddienst-Abschnitt ohne sechsten Fall,
Etappe-3-Anmeldeweg-Punkt in "Was diese Etappe NICHT entscheidet";
beide Dokument-Falsifizierungen durchgefuehrt und zurueckgenommen
- .planning/WINDOWS.md: zwei neue offene Eintraege (#28 verschluckte Leere
im Frontend, Familie #23/#25/#26; #29 Rechteausweitung ADMIN->SUPER_ADMIN
im Schwesterweg PATCH /users/:id, T-FH9-05)
Baseline wiederhergestellt: 951/951 Tests gruen in 60 Dateien (927+23
neue Faelle plus der in Aufgabe 2 erwartungsgemaess rote Test), Werkzeug
120/120, Typpruefung sauber.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AMASaSxv5QMY7RncqZriRR