diff --git a/.planning/STATE.md b/.planning/STATE.md index ef44f75..88957d7 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -31,7 +31,7 @@ See: .planning/PROJECT.md (updated 2026-07-17) Phase: 18 (desktop-client-fertigstellen) — COMPLETE (2026-09-17, Verifikation passed, Windows-Bedienprobe bestanden) Plan: 6 of 6 Status: Alle 18 Phasen abgeschlossen; Version 1.2.0 freigegeben. Kein laufender Meilenstein. Nach 1.2.0 auf main (Beta): Bildmarke in Akzentfarbe, CI-Desktop-Skip, Favoriten-Symbol/-Sortierung, Desktop-Server-Adresse, Update in der App (signiert), Versionszeile auf der Setup-Seite — alles verifiziert und auf VM/CI nachgewiesen -Last activity: 2026-10-09 - Completed quick task 261009-ikt: Cert-Manager-Umbau +Last activity: 2026-10-09 - Completed quick task 261009-of3: Anleitungen gegen Code geprueft Progress: [██████████] 99% @@ -505,6 +505,7 @@ Gerettet aus `.continue-here.md`. Relevant fuer die noch offenen Live-Tests. | 261008-who | Eigene Module beim Start vorladen (je Benutzer, Schalter in Modulansicht + Einstellungen), Keep-alive-Grenze 5→8, vorgeladene nie verworfen | 2026-10-09 | 86495ae | [261008-who-eigene-module-beim-start-vorladen](.planning/quick/261008-who-eigene-module-beim-start-vorladen/) | | 261009-dkv | Modul Dateien Etappe 2a: Teilen (Personen, Gruppen, Links nach Nextcloud-Regeln, Von mir/Mit mir geteilt), Review-Fixes, Nur-Ansehen-Ordner ohne Hochladen; Verifikation: Needs Review (Firmen-Nextcloud) | 2026-10-09 | d487a00 | [261009-dkv-modul-dateien-etappe-2a-teilen-von-datei](.planning/quick/261009-dkv-modul-dateien-etappe-2a-teilen-von-datei/) | | 261009-ikt | Cert Manager Umbau: gemeinsamer Reiter Dateien (mehrere Dateien, ZIP, Text), Kette/Fullchain mit Signaturpruefung, alle Formate inkl. EC, PFX kompatibel/modern, Vorlagen fuer 6 Zielsysteme, Fehlendes Zertifikat holen (AIA), Adressschutz gehaertet, Review-Fixes (ZIP-Bombe, PEM-Scanner, Umlaut-PFX); Modul 1.2.0; Verifikation: Verified | 2026-10-09 | 4b87249 | [261009-ikt-cert-manager-umbau-mehrere-dateien-zip-f](.planning/quick/261009-ikt-cert-manager-umbau-mehrere-dateien-zip-f/) | +| 261009-of3 | Alle vier Anleitungen gegen Code geprueft (5 Pruefer) und nachgearbeitet; Willkommensmail-Hinweis sechs Felder | 2026-10-09 | — | [261009-of3-anleitungen-gegen-code-pruefen-und-nacha](.planning/quick/261009-of3-anleitungen-gegen-code-pruefen-und-nacha/) | ## Deferred Items @@ -548,6 +549,6 @@ sind. Kein Anlass, sie vorher erneut vorzulegen. Last session: 2026-10-09T09:40:00Z Resumed: 2026-10-09 ueber /gsd-resume-work (HANDOFF eingelesen und entfernt; CI 41a5754 gruen). -Stopped at: Teilen (261009-dkv) und Cert Manager (261009-ikt) fertig. Naechstes laut User 09.10.: Anleitungen pruefen/nacharbeiten; danach Sicherheitsprotokoll/CI-Scanner, Dateien-Suche. +Stopped at: Teilen, Cert Manager (jetzt Zertifikatsmanager) und Anleitungs-Pruefung fertig und gepusht. Naechstes: Sicherheitsprotokoll/CI-Scanner, danach Dateien-Suche. Resume file: None Last activity: 2026-09-29 - Quick 260929-if2 Erinnerungen-Widget (lokal, nicht gepusht); v1.7.0 auf alpha+live diff --git a/.planning/quick/261009-of3-anleitungen-gegen-code-pruefen-und-nacha/261009-of3-SUMMARY.md b/.planning/quick/261009-of3-anleitungen-gegen-code-pruefen-und-nacha/261009-of3-SUMMARY.md new file mode 100644 index 0000000..6393393 --- /dev/null +++ b/.planning/quick/261009-of3-anleitungen-gegen-code-pruefen-und-nacha/261009-of3-SUMMARY.md @@ -0,0 +1,26 @@ +--- +status: complete +quick_id: 261009-of3 +date: 2026-10-09 +--- +# Quick 261009-of3: Anleitungen gegen Code pruefen und nacharbeiten + +Five gsd-doc-verifier runs (Anwender, Administration, Betrieb, Entwicklung 1-540, 541-end) wrote +verify-*.json in this directory; four gsd-doc-writer runs fixed every wrong/outdated finding and +added the missing items, each checked against the code. + +- Anwender: Benutzermenue „Einstellungen“, zehn Module, Nextcloud-Status-Kachel, Passwort + vergessen/aendern, Marktplatz „Kein Zugriff“/Detailseite, Zertifikatsmanager Zaehler + „Alle entfernen“, + Reiter Kantine/Handelsware. +- Administration: LDAP „Zeitplan“ (Intervall 60 min beim ersten Speichern), Domains/Dateien in Verwalten- + Tabelle, Modulliste, Zertifikatsmanager/Domaincheck, SMTP-Aufbau, {{firma}} = „Name Ihrer Organisation“. +- Betrieb: migrate-and-start.sh, TESSERA_MIGRATE_DATABASE_URL, CALENDAR_ENCRYPTION_KEY, CORS_ORIGIN, + APP_*, DASHBOARD_IMAGES_DIR/FAVORITE_ICONS_DIR, alte MAIL_*-Namen, SMTP-From-Default, Port 3001, + ZIP-Grenzen, Fehlerbild DATABASE_URL. +- Entwicklung: zehn Modulverzeichnisse, ModuleGrant.level, vollstaendige Backend-Liste, Stempelpfade, + eigene Module, /changelog, zwoelf Kacheltypen, Waechter-Tests, Compose-Dateien, forTenant/forSystem, + RLS-Waechter-Specs. +- Code: Platzhalter-Hinweis Willkommensmail „vier“ -> „sechs Felder“ (de/en) + CHANGELOG. +- CLAUDE.md: Desktop-Zeile nicht mehr „scaffolding only“. + +Gates: web vitest src/messages + admin 121 green. diff --git a/.planning/quick/261009-of3-anleitungen-gegen-code-pruefen-und-nacha/verify-administration.json b/.planning/quick/261009-of3-anleitungen-gegen-code-pruefen-und-nacha/verify-administration.json new file mode 100644 index 0000000..f3c9765 --- /dev/null +++ b/.planning/quick/261009-of3-anleitungen-gegen-code-pruefen-und-nacha/verify-administration.json @@ -0,0 +1,66 @@ +{ + "doc": "docs/anleitung-administration.md", + "claims_checked": 140, + "ok_count": 133, + "wrong": [ + { + "line": 198, + "claim": "Der Schalter „Aktiviert/Deaktiviert“ liegt im Abschnitt „Synchronisation“ (auch Fehlersuche Zeile 449: „im Sync-Bereich der LDAP-Konfiguration“).", + "actual": "Der Schalter (isActive) sitzt im eigenen Abschnitt „Zeitplan“ zusammen mit dem Sync-Intervall; der Abschnitt „Synchronisation“ enthält nur „Jetzt synchronisieren“ und den Ergebnisbericht. Der Zeitplan-Abschnitt hat auch einen eigenen Speichern-Knopf.", + "evidence": "apps/web/src/app/(portal)/admin/ldap/page.tsx:1246-1305 (Section 3a, title=controlCenter.ldap.schedule); :1310 (Section 3b sync.title); apps/web/src/messages/de.json:2273 (\"schedule\": \"Zeitplan\")", + "fix": "Abschnitt „Synchronisation“ aufteilen: „Zeitplan“ (Sync-Intervall in Minuten + Schalter Aktiviert/Deaktiviert, mit Speichern) und „Synchronisation“ (Jetzt synchronisieren + Ergebnisbericht). In Kapitel 4 (Zeile 193-198) und in der Fehlersuche (Zeile 449) „im Sync-Bereich“ durch „im Abschnitt „Zeitplan““ ersetzen." + } + ], + "outdated": [ + { + "line": 246, + "claim": "Tabelle „Was ‚Verwalten‘ je Modul freischaltet“ nennt nur Kantinenabrechnung, Handelsware, Proxmox, Nextcloud-Status, DKV-Rechnung.", + "actual": "Auch Domains und Dateien (Nextcloud) kennen die Stufe „Verwalten“; sie sind weiter unten in eigenen Abschnitten beschrieben, fehlen aber in dieser Übersichtstabelle. Das Wort „Verwalten“-Gating steckt auch in den Controllern von domains und nextcloud-files.", + "evidence": "apps/api/src/domains/domains.controller.ts, apps/api/src/nextcloud-files/nextcloud-files.controller.ts (requireManage/Stufe), Doc Zeilen 361 und 407", + "fix": "Zwei Zeilen ergänzen: „Domains: Anbindung einrichten, Kunden/Kontakte anlegen, Domains registrieren“ und „Dateien: Reiter „Einstellungen“ ansehen und „Verbindung prüfen“ (Adresse ändern nur Administratoren)“." + }, + { + "line": 87, + "claim": "{{firma}} = „Name des Mandanten“", + "actual": "Oberfläche nennt es „Name Ihrer Organisation“ (technisch Mandantenname). Inhaltlich gleich, Wortlaut weicht ab.", + "evidence": "apps/web/src/messages/de.json:~812 (placeholders.items.firma.meaning)", + "fix": "„Name Ihrer Organisation (der Mandantenname)“." + }, + { + "line": 78, + "claim": "Platzhalter funktionieren in allen sechs Feldern.", + "actual": "Doc stimmt mit dem Code (6 Felder, WELCOME_MAIL_LIMITS), aber der UI-Text placeholders.intro sagt noch „in allen vier Feldern“ (UI-Text veraltet, nicht die Anleitung).", + "evidence": "apps/web/src/messages/de.json (admin.welcomeMail.placeholders.intro); packages/shared/src/index.ts:346-353", + "fix": "Keine Änderung an der Anleitung nötig; UI-Text separat auf „sechs“ korrigieren." + }, + { + "line": 195, + "claim": "Sync-Intervall: 0 = deaktiviert; kein Standardwert genannt.", + "actual": "Beim erstmaligen Anlegen der Konfiguration setzt der Service 60 Minuten als Standard (Prisma-Schema-Default ist 0). Der Standardwert fehlt in der Anleitung.", + "evidence": "apps/api/src/ldap/ldap-config.service.ts:180 (syncIntervalMin ?? 60); apps/api/prisma/schema.prisma:94", + "fix": "Ergänzen: „Beim ersten Speichern der Verbindung ist das Intervall mit 60 Minuten vorbelegt.“" + } + ], + "missing_features": [ + { + "feature": "Abschnitt „Zeitplan“ der LDAP-Seite (Intervall + Anbindung ein/aus mit eigenem Speichern)", + "where": "apps/web/src/app/(portal)/admin/ldap/page.tsx:1246 ; de.json controlCenter.ldap.schedule/scheduleHelp", + "suggested_section": "4 AD-/LDAP-Anbindung > Synchronisation (eigener Unterabschnitt „Zeitplan“)" + }, + { + "feature": "Aufbau der SMTP-Seite in drei Abschnitten (Server / Absender und Empfänger / Prüfen und speichern) und Passwort-anzeigen-Knopf", + "where": "apps/web/src/messages/de.json controlCenter.smtp.*, settings.smtp.showPassword; apps/web/src/components/settings/smtp-settings-form.tsx", + "suggested_section": "6 SMTP (kurzer Hinweis auf Abschnitte)" + }, + { + "feature": "Markierung „System“ und Versionsanzeige in der Modulliste (Administration > Module); Rückverweise „Freigaben-Matrix“ / „Kategorien“", + "where": "apps/web/src/app/(portal)/admin/modules/page.tsx:190 ; de.json adminModules.system/version/grantsLink/categoriesLink", + "suggested_section": "5 Modul aktivieren" + }, + { + "feature": "Module Zertifikatsmanager (Seed-Name „Zertifikatsmanager“, Kategorie „Sicherheitswerkzeuge“), Domaincheck und Ausschreibungs-Radar tauchen als Module in der Admin-Modulliste auf, werden in der Anleitung aber nur teilweise erwähnt (Radar nur als Admin-Einstellungen, Zertifikatsmanager und Domaincheck gar nicht)", + "where": "apps/api/src/cert-manager/cert-manager.seed.ts:19 ; apps/api/src/domaincheck/domaincheck.seed.ts:18 ; apps/api/src/tenders/tenders.seed.ts:20", + "suggested_section": "5 Modulverwaltung (Übersichtstabelle der Module mit Kategorie und ob „Verwalten“ eine Wirkung hat)" + } + ] +} diff --git a/.planning/quick/261009-of3-anleitungen-gegen-code-pruefen-und-nacha/verify-anwender.json b/.planning/quick/261009-of3-anleitungen-gegen-code-pruefen-und-nacha/verify-anwender.json new file mode 100644 index 0000000..c4566e7 --- /dev/null +++ b/.planning/quick/261009-of3-anleitungen-gegen-code-pruefen-und-nacha/verify-anwender.json @@ -0,0 +1,71 @@ +{ + "doc": "docs/anleitung-anwender.md", + "claims_checked": 230, + "ok_count": 224, + "wrong": [ + { + "line": 56, + "claim": "Benutzermenue enthaelt getrennt: Einstellungen, Administrator (nur fuer Admins), Abmelden", + "actual": "Das Benutzermenue hat nur einen Eintrag fuer Einstellungen: fuer Admins heisst er 'Einstellungen/Administration', fuer Benutzer 'Einstellungen'. Einen Eintrag 'Administrator' gibt es nicht. Die Administration erreicht man ueber die Seitenleiste der Einstellungen (Zeile 339 des Dokuments stimmt).", + "evidence": "apps/web/src/components/layout/header.tsx:232; apps/web/src/messages/de.json:82 (header.settingsAdmin)", + "fix": "Zeilen 56-57 ersetzen durch: '**Einstellungen** (bei Administratoren: **Einstellungen/Administration**) - fuehrt zu Ihren persoenlichen Einstellungen, Administratoren erreichen von dort auch die Administration' und den Punkt 'Administrator' streichen." + }, + { + "line": 119, + "claim": "Aktuell stehen in Tessera sieben Module zur Verfuegung.", + "actual": "Es gibt zehn Module mit Seed: Ausschreibungs-Radar, DKV-Rechnung, Zertifikatsmanager, Domaincheck, Domains, Proxmox, Nextcloud-Status, Dateien, Kantinenabrechnung, Handelsware. Das Dokument beschreibt selbst zehn.", + "evidence": "apps/api/src/*/*.seed.ts (10 Dateien, name: ...); Inhaltsverzeichnis Zeilen 14-23", + "fix": "'Aktuell stehen in Tessera zehn Module zur Verfuegung.' (oder Zahl weglassen: 'Folgende Module stehen zur Verfuegung.')" + }, + { + "line": 461, + "claim": "Stolperstein: 'Zahlen, die Sie ueber Meine Quellen im Ausschreibungs-Radar eingebracht haben, tauchen in der Trefferliste aller Kollegen auf.'", + "actual": "Inhaltlich gemeint sind Ausschreibungen, nicht 'Zahlen' (Tippfehler/irrefuehrend). Die Aussage selbst stimmt mit tenderRadar.mySources.intro ueberein.", + "evidence": "apps/web/src/messages/de.json:1833", + "fix": "'Ausschreibungen, die ueber Ihr Postfach oder Ihre Feeds (Meine Quellen) hereinkommen, tauchen in der Trefferliste aller Kolleginnen und Kollegen auf.'" + }, + { + "line": 156, + "claim": "Zertifikatsmanager: 'zusammen hoechstens 10 MB' (Dateien-Reiter)", + "actual": "Die Oberflaeche begrenzt auf 10 MB (working-set.ts), der API-Endpunkt erlaubt 20 MB gesamt. Fuer Anwender gilt die 10-MB-Grenze der Oberflaeche, daher fachlich korrekt; nur zur Kenntnis (Abweichung Web 10 MB vs. API 20 MB).", + "evidence": "apps/web/src/app/(portal)/modules/cert-manager/working-set.ts:12; apps/api/src/cert-manager/cert-manager.controller.ts:16", + "fix": "Keine Aenderung noetig; optional pruefen, ob API-Grenze absichtlich hoeher ist." + } + ], + "outdated": [ + { + "line": 88, + "claim": "Tabelle 'Verfuegbare Widgets' listet elf Widgets", + "actual": "Die Registry kennt zwoelf Widget-Typen; 'Nextcloud-Status' (Ampeluebersicht) fehlt in der Tabelle, ist nur im Modulabschnitt (Zeile 256) beschrieben.", + "evidence": "apps/web/src/components/dashboard/widget-registry.tsx:446-547 (nextcloud-status); apps/web/src/messages/de.json:~530 (dashboard.nextcloudStatus)", + "fix": "Zeile in die Widget-Tabelle aufnehmen: 'Nextcloud-Status | Ampeluebersicht Ihrer Nextcloud-Clouds (Gruen/Gelb/Rot); nur fuer Benutzer mit Zugriff auf das Modul; siehe Modul Nextcloud-Status'." + } + ], + "missing_features": [ + { + "feature": "Marktplatz-Status 'Kein Zugriff' (Modul aktiv, aber keine Freigabe) und Hinweis-Toast 'Kein Zugriff auf dieses Modul - wenden Sie sich an Ihren Administrator'", + "where_in_code": "apps/web/src/messages/de.json:1211-1250 (marketplace.statusNoAccess, toastNoAccess)", + "suggested_section": "Marktplatz (neben 'Aktiviert' und 'Verfuegbar')" + }, + { + "feature": "Detailseite zeigt 'Nicht aktiviert' / 'Aktiviert' (detailStatusInactive) sowie 'Zurueck zum Marktplatz'", + "where_in_code": "apps/web/src/messages/de.json marketplace.detailStatus*", + "suggested_section": "Marktplatz (Detailseite)" + }, + { + "feature": "Zertifikatsmanager: 'Alle entfernen' sowie Reiter-Zaehler 'Dateien (n)'", + "where_in_code": "apps/web/src/messages/de.json certManager.files.removeAll, tabs.filesWithCount", + "suggested_section": "Zertifikatsmanager > Dateien" + }, + { + "feature": "Seite 'Passwort zuruecksetzen' (Link aus der E-Mail von 'Passwort vergessen?') und Seite 'Passwort aendern' bei erzwungener Aenderung als eigene Schritte", + "where_in_code": "apps/web/src/app/(auth)/reset-password, apps/web/src/app/(portal)/change-password", + "suggested_section": "Anmeldung (kurz den Ablauf nach dem Klick auf den Link in der Mail beschreiben)" + }, + { + "feature": "Reiter-Namen von Handelsware (Import, Konten, Einstellungen) und Kantinenabrechnung (Abrechnung, Einstellungen) nicht vollstaendig benannt; Reiter 'Import' bzw. 'Abrechnung' wird nicht namentlich genannt", + "where_in_code": "apps/web/src/messages/de.json:1901 (kantineDatev.tabs), 1981 (handelswareDatev.tabs)", + "suggested_section": "Kantinenabrechnung / Handelsware" + } + ] +} diff --git a/.planning/quick/261009-of3-anleitungen-gegen-code-pruefen-und-nacha/verify-betrieb.json b/.planning/quick/261009-of3-anleitungen-gegen-code-pruefen-und-nacha/verify-betrieb.json new file mode 100644 index 0000000..4471d25 --- /dev/null +++ b/.planning/quick/261009-of3-anleitungen-gegen-code-pruefen-und-nacha/verify-betrieb.json @@ -0,0 +1,75 @@ +{ + "doc": "docs/anleitung-betrieb.md", + "claims_checked": 120, + "ok_count": 116, + "wrong": [ + { + "line": 276, + "claim": "Kapitel 5: Der api-Container führt Migrationen per CMD `prisma migrate deploy --schema apps/api/prisma/schema.prisma && node apps/api/dist/main.js` aus (apps/api/Dockerfile, CMD)", + "actual": "Das CMD ist jetzt `sh apps/api/scripts/migrate-and-start.sh`. Das Skript bricht ohne DATABASE_URL mit 'FEHLER: DATABASE_URL ist nicht gesetzt.' ab, führt `prisma migrate deploy` mit TESSERA_MIGRATE_DATABASE_URL (Rückfall DATABASE_URL) aus und startet Node per `exec node apps/api/dist/main.js`.", + "evidence": "apps/api/Dockerfile:59; apps/api/scripts/migrate-and-start.sh:25-48", + "fix": "Codeblock und Text in Kapitel 5 ersetzen: 'Der api-Container startet über apps/api/scripts/migrate-and-start.sh: erst prisma migrate deploy (Verbindung TESSERA_MIGRATE_DATABASE_URL, falls gesetzt, sonst DATABASE_URL), danach exec node apps/api/dist/main.js.' Satz 'startet node ... erst gar nicht' bleibt sinngemäß richtig (set -e)." + } + ], + "outdated": [ + { + "line": 153, + "claim": "Tabelle in Kapitel 3 listet die Prod-Variablen vollständig", + "actual": "docker-compose.prod.yml reicht zusätzlich TESSERA_MIGRATE_DATABASE_URL (Default leer) und CALENDAR_ENCRYPTION_KEY an die api durch. Letzteres wird nur in der Zeile von TESSERA_ENCRYPTION_KEY erwähnt, ersteres gar nicht.", + "evidence": "docker-compose.prod.yml:38,58", + "fix": "Zeile für TESSERA_MIGRATE_DATABASE_URL ergänzen (optional, getrennte Verbindung mit Tabelleneigentümer-Rechten nur für den Migrationsschritt; leer = DATABASE_URL)." + }, + { + "line": 393, + "claim": "Fehlerzeile: 'api wird nie healthy, Log zeigt Verbindungsfehler von Prisma' ohne Hinweis auf den neuen Startabbruch", + "actual": "Ist DATABASE_URL leer, beendet migrate-and-start.sh den Container mit 'FEHLER: DATABASE_URL ist nicht gesetzt.' bevor Prisma verbindet.", + "evidence": "apps/api/scripts/migrate-and-start.sh:17-20", + "fix": "Symptomzeile 'Log zeigt FEHLER: DATABASE_URL ist nicht gesetzt.' in Kapitel 7 ergänzen." + }, + { + "line": 152, + "claim": "Beschreibung von TESSERA_SMTP_* nennt keinen Default für _FROM", + "actual": "Default in Prod-Compose ist 'Tessera '.", + "evidence": "docker-compose.prod.yml:49", + "fix": "Default für TESSERA_SMTP_FROM in der Tabelle nennen (Hinweis: .env.prod.example sagt, die UI-Einstellung überschreibt die Variable)." + } + ], + "missing": [ + { + "fact": "TESSERA_MIGRATE_DATABASE_URL (getrennte Migrationsverbindung)", + "where": "docker-compose.prod.yml:38; apps/api/scripts/migrate-and-start.sh; docs/mandantentrennung-datenbankrolle.md", + "section": "Kapitel 3 Tabelle und Kapitel 5" + }, + { + "fact": "CORS_ORIGIN wird in main.ts gelesen (Default http://localhost:3000). Steht nur in einem VERIFY-Kommentar, ist in keiner Compose-Datei gesetzt.", + "where": "apps/api/src/main.ts:10", + "section": "Kapitel 3 (kurz nennen; für den Browser-Weg über /api-proxy unkritisch)" + }, + { + "fact": "DASHBOARD_IMAGES_DIR und FAVORITE_ICONS_DIR überschreiben die Ablageorte der Bilderrahmen-/Favoriten-Dateien (Tests/Abweichung vom Volume-Pfad)", + "where": "apps/api/src (process.env.DASHBOARD_IMAGES_DIR, FAVORITE_ICONS_DIR)", + "section": "Kapitel 6 (Hinweis: bei Änderung muss das Volume mitwandern) oder Kapitel 3" + }, + { + "fact": "Build-Argumente/Laufzeit-ENV APP_VERSION, APP_CHANNEL, APP_COMMIT, APP_BUILD_TIME speisen /health/version; werden von publish-images.sh gesetzt, nicht per .env", + "where": "apps/api/Dockerfile:4-7,31-35; .gitea/scripts/publish-images.sh", + "section": "Kapitel 9 'Woran Sie erkennen...' (Erklärung, warum buildTime/commit auf selbst gebauten Images 'dev' zeigen)" + }, + { + "fact": "Veraltete SMTP-Rückfallnamen MAIL_HOST/MAIL_PORT/MAIL_USER/MAIL_PASS werden im Code gelesen", + "where": "apps/api/src (configService.get('MAIL_*'))", + "section": "Kapitel 3, nur falls noch unterstützt (prüfen, ob Totcode)" + }, + { + "fact": "Das Basis-Compose (docker-compose.yml) mappt Host-Port 3001 ebenfalls; docker-compose.prod.yml gibt keine Host-Ports für db frei -- stimmt, aber Hinweis auf Firewall für 3001 fehlt als Sicherheitsempfehlung", + "where": "docker-compose.prod.yml:30-31", + "section": "Kapitel 1" + }, + { + "fact": "Der Zertifikatsmanager entpackt ZIP-Dateien zusätzlich mit höchstens 100 Einträgen und Kompressionsverhältnis 100", + "where": "apps/api/src/cert-manager/zip-expand.ts:37-42", + "section": "Kapitel 3, Abschnitt Zertifikatsmanager (Rechenaufwand)" + } + ], + "verified_ok_summary": "Compose-Dienste, Ports 3000/3001, kein db-Host-Port, Netzwerke (data-net internal), Healthchecks (Intervalle, start_period 10s Basis/20s Prod), web ohne Healthcheck, Volumes pgdata/user-files mit Mount /app/user-files, IMAGE_TAG-Default beta, .env.prod.example (IMAGE_TAG=live, COMPOSE_FILE), ${TESSERA_ENCRYPTION_KEY:?...}-Abbruch (über CALENDAR-Fallback), CryptoService-Meldungen 'is not set' / '64-character hex string', Seed-Verhalten (findUnique, Tenant default), /health und /health/version, Logzeilen 'Tessera API running on port 3001' + formatAppVersionLine, API_INTERNAL_URL und /api-proxy-Rewrite in next.config.ts, NEXT_PUBLIC_API_URL=/api-proxy im web-Dockerfile, Migration 20260924120000_dashboard_image_drop_data mit exakt zitierter Fehlermeldung, publish-images.sh Etiketten (main: beta+latest, Tag: live+vX.Y.Z), ci.yml (Branches main/live, Tags v*, Job desktop needs test, CARGO_BUILD_JOBS=4, Secrets TAURI_SIGNING_*, publish needs desktop), publish-release.sh --tag, tauri.conf.json pubkey, DESKTOP_DIST_DIR, GET /desktop/latest|update|download/:platform, 204 beim Update-Endpunkt, Desktop-Meldungen (Update nur über https möglich, Update fehlgeschlagen, antwortet kein Tessera-Server, Auf Version ... aktualisieren), Parameter dv/dc/dos und Cookie tessera_desktop_client, Bug-Report-Kürzel [Browser]/[Desktop/Windows]/[Desktop/Linux]/[Desktop] und Logtexte 'Bug report' / 'Bug report mail failed', Zwischenspeicher-Logzeile 'Desktop unveraendert seit', Nextcloud-Grenzen (8 MiB Stück, 20 s Zusammenbau, 10/40 Freigaben je 10 min, 15 min Pause, Meldungstext), Zertifikatsmanager-Grenzen (30 Dateien, 5 MB, 20 MiB, 200/50/50, 1 Mio / 6 Mio KDF, 10 Passwörter, AIA 8 s / 256 KiB / 3 Weiterleitungen, 512 KiB JSON, ZIP 1 MiB/20 MiB, Meldung 'zusammen zu groß'), Ablagepfade user-files/avatars|dashboard-images|favorite-icons, dev-Compose (mailhog, openldap, phpldapadmin), docker-compose.ci.yml, Verweise docs/ci-cd-setup.md (Abschnitt 4) und anleitung-anwender.md (Kapitel Desktop-App). Nicht aus dem Repo prüfbar: Serverzustand /opt/tessera, Container-Namen tessera-api-1, Proxy-Einstellungen, Secrets in Gitea, Schlüssel unter ~/.tessera, Datum-Angaben (24.09., 14./15.09.)." +} diff --git a/.planning/quick/261009-of3-anleitungen-gegen-code-pruefen-und-nacha/verify-entwicklung-1.json b/.planning/quick/261009-of3-anleitungen-gegen-code-pruefen-und-nacha/verify-entwicklung-1.json new file mode 100644 index 0000000..11a99e9 --- /dev/null +++ b/.planning/quick/261009-of3-anleitungen-gegen-code-pruefen-und-nacha/verify-entwicklung-1.json @@ -0,0 +1,96 @@ +{ + "doc": "docs/anleitung-entwicklung.md", + "range": "1-540", + "claims_checked": 120, + "ok_count": 106, + "wrong": [ + { + "line": 245, + "claim": "Innerhalb von (portal) liegen ... vier fest verdrahtete Modulverzeichnisse (cert-manager, dkv-fleet, domaincheck, tender-radar) mit eigenen layout.tsx", + "actual": "Es gibt zehn Modulverzeichnisse mit eigenem layout.tsx (cert-manager, dkv-fleet, domaincheck, domains, handelsware-datev, kantine-datev, nextcloud-files, nextcloud-status, proxmox, tender-radar), dazu 'custom' ohne Layout. Auch MODULE_REGISTRY hat zehn Eintraege.", + "evidence": "apps/web/src/app/(portal)/modules/*/layout.tsx (10 Treffer); apps/web/src/lib/module-loader.ts:31-90", + "fix": "Von 'vier' auf 'zehn fest verdrahtete Modulverzeichnisse' aendern und alle zehn nennen (oder allgemein formulieren). Gleiches gilt fuer Zeile 403-405 und 416-419 ('jedem der vier')." + }, + { + "line": 403, + "claim": "Vier fest verdrahtete Modulverzeichnisse: cert-manager, dkv-fleet, domaincheck, tender-radar", + "actual": "Zehn Verzeichnisse; zusaetzlich domains, handelsware-datev, kantine-datev, nextcloud-files, nextcloud-status, proxmox (und 'custom' fuer eigene Module ohne Gate-Layout).", + "evidence": "apps/web/src/app/(portal)/modules/", + "fix": "Liste auf alle zehn erweitern bzw. 'vier' streichen. Der Code-Kommentar in [category]/[moduleSlug]/page.tsx nennt selbst noch 'four' (veraltet)." + }, + { + "line": 248, + "claim": "Backend-Domaenenmodule: auth, user, tenant, groups, module-registry, domaincheck, dkv, cert-manager, tenders, calendar, dashboard, favorites, settings, ldap, mail, crypto, health, prisma", + "actual": "Die Liste ist unvollstaendig; es fehlen accounting, bug-reports, common, custom-modules, desktop, domains, handelsware-datev, inbox, kantine-datev, module-categories, nextcloud-files, nextcloud-status, proxmox, reminders.", + "evidence": "ls apps/api/src", + "fix": "Liste um die fehlenden Verzeichnisse ergaenzen (common ist ein Hilfsordner, kein Fachmodul)." + }, + { + "line": 373, + "claim": "ModuleGrant traegt bewusst kein Rechtestufen-Feld, nur An/Aus (D-04)", + "actual": "ModuleGrant hat seit 261002-icv das Feld level (enum ModuleGrantLevel USE|MANAGE, Default USE). Nur 'Gruppe XOR Benutzer' (D-04) stimmt weiterhin. ModuleAccessService arbeitet mit getModuleAccessLevels, getAccessibleModuleIds ist nur die Schluesselmenge davon.", + "evidence": "apps/api/prisma/schema.prisma:160-164, 211-214; apps/api/src/module-registry/module-access.service.ts:118-131", + "fix": "Satz ersetzen: 'ModuleGrant traegt eine Freigabestufe (USE = Benutzen, MANAGE = Benutzen und Modul-Einstellungen aendern); Freigaben erteilen bleibt Administratoren vorbehalten. Gruppe oder Benutzer, nie beides.' Zeile 375-382: getAccessibleModuleIds als Schluesselmenge von getModuleAccessLevels beschreiben." + }, + { + "line": 296, + "claim": "Ein Modul erscheint im Marktplatz (GET /modules, GET /modules/catalog) ... ; seedModule laeuft aus Seed-Dateien", + "actual": "Teilweise ok: GET /modules und /catalog existieren. Aber der Code-Kommentar zu seedModule spricht von 'vier Seed-Dateien'; es sind zehn. (Kommentar, nicht Doku; Doku Z. 279 'Jedes Modul seedet sich' ist korrekt.)", + "evidence": "apps/api/src/module-registry/module-registry.service.ts:190-196", + "fix": "Kein Doku-Fehler; optional Code-Kommentar korrigieren." + }, + { + "line": 530, + "claim": "proxmox-widget-model.ts / components/proxmox/ ... 'Einstellungsformular ... components/settings/proxmox-widget-config-form.tsx'", + "actual": "Pfade stimmen. Kein Fehler (siehe ok_count).", + "evidence": "apps/web/src/components/settings/proxmox-widget-config-form.tsx", + "fix": "keine" + } + ], + "outdated": [ + { + "line": 33, + "claim": "apps/desktop ... Tauri-Desktop-Client, fertiges Produkt; CLAUDE.md-Tabelle sagt 'scaffolding only as of docs/anleitung-entwicklung.md'", + "actual": "Doku stimmt zum Code (lib.rs mit check_server/save_server_url, setup.html vorhanden). Veraltet ist die Aussage in CLAUDE.md (Desktop Wrapper: 'scaffolding only'), die auf diese Anleitung verweist.", + "evidence": "apps/desktop/src-tauri/src/lib.rs:858,888; CLAUDE.md Abschnitt Desktop Wrapper", + "fix": "CLAUDE.md anpassen; Anleitung unveraendert lassen." + }, + { + "line": 227, + "claim": "Stempel aus Version und letztem Commit an apps/desktop/, desktop-version.sh, desktop-collect.sh, desktop-stamp.sh und ci.yml", + "actual": "DESKTOP_PATHS enthaelt zusaetzlich .gitea/scripts/appimage-strip-wayland.sh.", + "evidence": ".gitea/scripts/desktop-stamp.sh:56", + "fix": "'appimage-strip-wayland.sh' in die Aufzaehlung aufnehmen." + }, + { + "line": 418, + "claim": "Der Fix (Commit 74a30fb/5504931) gibt jedem der vier Modulverzeichnisse ein eigenes layout.tsx", + "actual": "Commits existieren; heute tragen zehn Verzeichnisse das Layout (siehe wrong Z. 245).", + "evidence": "git cat-file -t 74a30fb / 5504931 = commit; modules/*/layout.tsx", + "fix": "'vier' durch 'alle fest verdrahteten' ersetzen; Test module-layouts.test.tsx als Wächter erwähnen." + }, + { + "line": 449, + "claim": "Domaincheck ist das kleinste vorhandene Modul", + "actual": "Nicht eindeutig pruefbar; es gibt jetzt weitere kleine Module (kantine-datev ohne components, nextcloud-status). Die aufgefuehrten Domaincheck-Dateien existieren alle.", + "evidence": "apps/web/src/app/(portal)/modules/kantine-datev/", + "fix": "Formulierung zu 'ein kleines Modul' abschwaechen." + }, + { + "line": 493, + "claim": "Kachel: drei Stellen; Bsp. nur Proxmox ('Erstes echtes Beispiel')", + "actual": "Zweite Modul-Kachel nextcloud-status existiert ebenfalls (WIDGET_MODULE_SLUGS), ebenso weitere Typen picture-frame, xframe, reminder.", + "evidence": "packages/shared/src/index.ts:102-137; apps/web/src/app/(portal)/page.tsx:38-49", + "fix": "nextcloud-status als zweites Modul-Kachel-Beispiel erwaehnen." + } + ], + "missing": [ + "Modulsystem-Kapitel nennt nur Domaincheck, DKV, Cert-Manager, Tender-Radar und Proxmox; undokumentiert sind die Module domains, handelsware-datev, kantine-datev, nextcloud-files, nextcloud-status (alle mit Seed, Changelog, MODULE_REGISTRY-Eintrag und Layout) sowie accounting (gemeinsam genutzt von Handelsware/Kantine).", + "Eigene Module (custom-modules, Frontend modules/custom/[id], admin/custom-modules, settings/custom-modules, components/modules/custom-module-*) fehlen im Modulsystem-Kapitel; Zeile 310-311 erwaehnt sie nur beilaeufig.", + "Frontend-Routen: (portal)/changelog fehlt in der Routenliste Z. 239 (admin, marketplace, modules, settings, change-password); Admin-Unterbereiche (custom-modules, groups, ldap, modules, smtp, tenants, users, welcome-mail) nicht beschrieben.", + "Backend-Bereiche ohne Erwaehnung: bug-reports, inbox, reminders, module-categories (Kategorien-Verwaltung, messages/module-categories.spec.ts), desktop-Controller (GET /desktop/latest, /update, /download/:platform) als API-Seite.", + "Dashboard-Kachel-Typen: picture-frame, xframe, reminder, nextcloud-status werden nicht genannt; WIDGET_TYPES hat zwoelf Eintraege.", + "Wächter-Tests im Frontend: modules/module-layouts.test.tsx (prueft Gate-Layouts) und messages/umlaut-guard.spec.ts / tenderRadar-parity.spec.ts nicht erwaehnt.", + "Root-Skripte: apps/api hat zusaetzlich test:watch und start:dev (nur Compose-Befehl 'nest start --watch' ist beschrieben, ueber pnpm --filter @tessera/api start:dev); docker-compose.prod.yml und docker-compose.ci.yml existieren, werden im Kapitel nicht erwaehnt." + ] +} diff --git a/.planning/quick/261009-of3-anleitungen-gegen-code-pruefen-und-nacha/verify-entwicklung-2.json b/.planning/quick/261009-of3-anleitungen-gegen-code-pruefen-und-nacha/verify-entwicklung-2.json new file mode 100644 index 0000000..5c2afaf --- /dev/null +++ b/.planning/quick/261009-of3-anleitungen-gegen-code-pruefen-und-nacha/verify-entwicklung-2.json @@ -0,0 +1,34 @@ +{ + "doc": "docs/anleitung-entwicklung.md", + "range": "541-1004", + "claims_checked": 120, + "wrong": [ + { + "line": "635-640", + "claim": "Das Dockerfile setzt als CMD: prisma migrate deploy --schema apps/api/prisma/schema.prisma && node apps/api/dist/main.js", + "actual": "Der CMD ist `sh apps/api/scripts/migrate-and-start.sh`. Das Skript trennt Migrations- und Laufzeitverbindung (TESSERA_MIGRATE_DATABASE_URL, Vorgabe DATABASE_URL), Rollentrennung gemäß docs/mandantentrennung-datenbankrolle.md.", + "evidence": "apps/api/Dockerfile:59; apps/api/scripts/migrate-and-start.sh:1-40", + "fix": "CMD-Block ersetzen durch `CMD [\"sh\", \"apps/api/scripts/migrate-and-start.sh\"]` und ergänzen: Das Skript führt `prisma migrate deploy` (mit TESSERA_MIGRATE_DATABASE_URL, falls gesetzt, sonst DATABASE_URL) aus und startet danach die API mit DATABASE_URL." + } + ], + "outdated": [ + { + "line": "549-550", + "claim": "forTenant() führt vor jeder Query SELECT set_config('app.current_tenant', $1, true) aus", + "actual": "Die Anweisung setzt drei Werte in einem Aufruf: app.current_tenant, app.current_user (leer, wenn kein userId) und app.system_context (leer).", + "evidence": "apps/api/src/prisma/prisma-tenant.extension.ts:201", + "fix": "Ergänzen: 'setzt zugleich app.current_user (optionaler dritter Parameter) und löscht app.system_context'." + } + ], + "missing": [ + { + "line": "558-566", + "claim": "RLS-Abschnitt", + "actual": "Es gibt zusätzlich eine Systemkontext-Variante (app.system_context='true', Zeile 228 der Extension) und Wächter-Specs rls-coverage/rls-access-inventory/rls-app-role/rls-preflight in apps/api/src/prisma/, die nicht erwähnt werden.", + "evidence": "apps/api/src/prisma/prisma-tenant.extension.ts:228; apps/api/src/prisma/*.spec.ts", + "fix": "Kurz die RLS-Wächter-Specs und den Systemkontext-Weg (für Hintergrunddienste) erwähnen." + } + ], + "ok_count": 119, + "notes": "Geprüft und korrekt: TenantGuard/APP_GUARD-Reihenfolge, x-tenant-id, req.tenantId; RLS-Zählung 23 = 4+3+16; zehn persönliche Tabellen in Migration 20260911120000; plattformweite Modelle ohne tenantId; Role-Enum; RolesGuard global; module-grants Routen und Rollen (matrix vor users/:userId); postinstall-Skript; Vitest-Konfigurationen (node/jsdom, setup.ts, passWithNoTests); Testbefehle; Desktop-Spec mit NestFactory; CI-Job desktop mit cargo check/clippy; Tenders-Routenreihenfolge (alle genannten statischen Routen vor @Get(':id')); CHANGELOG-Mechanik (next.config, Dockerfile, .dockerignore, publish-release.sh exit 1, filterChangelogForChannel); Release-Fenster (Endpunkte, getRunningRelease, parse/compareReleaseVersions, selectReleaseNotice, User.lastSeenReleaseVersion); Dashboard-Hintergrund (Spalte, Endpunkt, getMe, shared-Parser); i18n-Wächter-Specs; @custom-variant dark in globals.css:22; Nextcloud-Teilen (nextcloud-shares.ts, Grenzen 8 MiB/64 KiB/1 MiB, Routen, checkShareCreate 10 und checkShareAttempt 40 je 10 min, mapShareFailure, e2e-shares.sh mit Argumenten und policy_wait); Zertifikatsmanager (3 POST-Routen, Limits 30/5/20 MiB, 200/50/50, KDF 1.000.000/6.000.000, ZIP-Grenzen, PEM_BLOCKS 1000, 512 KiB certBuildJsonBody, http-setup, createGuardedLookup, AIA 8 s/256 KiB, public-url-guard Exporte, Fixtures, e2e-cert.sh)." +}