--- phase: quick-260917-h2s plan: 01 subsystem: desktop-client, web-middleware tags: [desktop, tauri, nextjs, middleware, ux] status: complete dependency-graph: requires: [] provides: - "with_desktop_marker / update_labels (apps/desktop/src-tauri/src/lib.rs)" - "withDesktopCookie (apps/web/src/middleware.ts)" - "isDesktopClient / useIsDesktopClient (apps/web/src/lib/desktop-client.ts)" - "DesktopContextMenuGuard (apps/web/src/components/desktop/desktop-context-menu-guard.tsx)" affects: - "apps/web/src/components/desktop/desktop-download-links.tsx" - "apps/web/src/app/layout.tsx" - "apps/desktop/src-tauri/tauri.conf.json" tech-stack: added: [] patterns: - "Cookie-basierte Client-Erkennung: Query-Parameter auf der ersten Navigation -> Middleware setzt Cookie auf jeder Antwort -> Hook liest es hydration-sicher" key-files: created: - apps/web/src/lib/desktop-client.ts - apps/web/src/lib/desktop-client.test.ts - apps/web/src/middleware.test.ts - apps/web/src/components/desktop/desktop-context-menu-guard.tsx - apps/web/src/components/desktop/desktop-context-menu-guard.test.tsx modified: - apps/desktop/src-tauri/src/lib.rs - apps/desktop/src-tauri/tauri.conf.json - apps/desktop/src-tauri/icons/nsis-header.bmp - apps/desktop/src-tauri/icons/nsis-sidebar.bmp - apps/web/src/middleware.ts - apps/web/src/components/desktop/desktop-download-links.tsx - apps/web/src/components/desktop/desktop-download-links.test.tsx - apps/web/src/app/layout.tsx - CHANGELOG.md - docs/anleitung-anwender.md - docs/anleitung-entwicklung.md decisions: - "Beim Handbuchsatz zu Trotzdem ausführen wurde Der Grund dafür zu Der Grund für die Windows-Meldung umformuliert, weil der neu eingefuegte Satz sonst den Bezug des Pronomens verschoben haette (redaktionelle Praezisierung, kein inhaltlicher Unterschied zum Plan)." metrics: duration: 24min completed: 2026-09-17 actuals: tokens: 39000 tasks: 3 commits: 3 plan_head_before: 98fad86 --- # Phase quick-260917-h2s Plan 01: Desktop-Client-Erkennung, Beta-Label, deutscher Installer Summary Der Desktop-Client meldet sich jetzt beim Web per Cookie an, wodurch Download-Links und das Browser-Kontextmenü in der App verschwinden; der Beta-Update-Hinweis nennt bei gleicher Version den Commit-Stand statt der verwirrenden gleichen Versionsnummer, und der Windows-Installer läuft auf Deutsch mit Tessera-Grafik und -Symbol. ## Was wurde gebaut **Task 1 — Rust (`apps/desktop/src-tauri/src/lib.rs`, Commit `5bdabf5`):** - `with_desktop_marker(url)` hängt `desktop=1` als Query-Paar an einen Klon der Adresse an; beide `window.navigate`-Aufrufe (`save_server_url`, Startnavigation im `setup`) nutzen sie. Der im Store gespeicherte `server_url`-Wert bleibt unverändert (Parameter geht nur in die Navigation). - `update_labels(version_changed, version, commit)` liefert Menü-/Benachrichtigungstext: bei Versionswechsel wie bisher „Version {v} herunterladen"; bei gleicher Version (Beta-Kanal, neuer Commit) „Neuen Beta-Stand herunterladen" / „Neuer Beta-Stand {commit} verfügbar …". - `mod tests` deckt beide Helfer ab (5 Tests); `cargo fmt --check`, `cargo check`, `cargo clippy`, `cargo test --lib` grün. **Task 2 — Web, Tracer (Commit `d9b94bd`):** - `withDesktopCookie` in `middleware.ts` setzt `tessera_desktop=1` (Path `/`, ein Jahr, `SameSite=lax`, ohne `HttpOnly`, `Secure` nur bei https) auf **jede** Antwort der `middleware`-Funktion, sobald `?desktop=1` anliegt — auch auf dem Frühausstieg für öffentliche Routen und auf Redirects. Die von Plan 260917-gyd zwischenzeitlich ergänzten Rückgaben (u. a. der `next`-Redirect) sind mit eingeschlossen. - `apps/web/src/lib/desktop-client.ts`: `isDesktopClient()` liest das Cookie synchron (SSR-sicher: `false` ohne `document`); `useIsDesktopClient()` kapselt es per `useEffect`, damit Server- und erster Client-Render übereinstimmen. - `DesktopDownloadLinks` bricht den Ladeeffekt im Desktop-Client vor dem Request ab und rendert nichts. - `DesktopContextMenuGuard` (neu, in `layout.tsx` eingebunden) unterdrückt das WebView2-Kontextmenü außerhalb von Eingabefeldern/contenteditable-Bereichen. - Tracer-Gate: Die komplette Kette (Anfrage mit `?desktop=1` → Cookie auf der Antwort → Hook → Komponente rendert nichts) wurde Ende-zu-Ende durch die volle Testsuite (`pnpm --filter @tessera/web exec vitest run`, 417/417 grün) und `type-check` bestätigt, bevor Task 3 begann. **Task 3 — Installer, CHANGELOG, Handbuch (Commit `2cd4adc`):** - `bundle.windows.nsis` in `tauri.conf.json`: `languages: ["German"]`, `displayLanguageSelector: false`, `installerIcon`, `headerImage`, `sidebarImage`, `installMode: "currentUser"`. - Beide BMPs aus dem Scratchpad nach `icons/` kopiert (`nsis-header.bmp` 150×57, `nsis-sidebar.bmp` 164×314, beide `BMP3`). - CHANGELOG: vier neue `Desktop-App:`-Stichpunkte (zwei unter „Geändert", zwei unter „Behoben"). - `docs/anleitung-anwender.md`: Satz zum deutschen Installationsassistenten (kein Admin nötig); Tray-Eintrag „Update herunterladen" erklärt (Beta-Text). - `docs/anleitung-entwicklung.md`: Ort der nsis-Konfiguration und Hinweis, dass nur der CI-Bau auf Windows den echten Nachweis liefert. ## Deviations from Plan ### Auto-fixed Issues None — plan executed exactly as written. Eine redaktionelle Umformulierung (siehe `decisions` oben) war nötig, damit ein Pronomenbezug im Handbuchsatz nicht verrutscht; inhaltlich deckt sich der Text mit der Plan-Vorgabe. ## Offene Nachweise (nicht lokal prüfbar) Wie im Plan vorgesehen, bleibt der Beweis über die WebView2-Grenze durch den Orchestrator nach dem CI-Bau auf der Windows-VM offen: - Cookie `tessera_desktop=1` im echten Client gesetzt (Bedienprobe) - Keine Download-Links auf der Anmeldeseite im Client - Kein Browser-Kontextmenü im Client, aber in Eingabefeldern erhalten - Beta-Label „Neuen Beta-Stand herunterladen" / Benachrichtigung mit Commit-Kürzel - Deutscher Installer mit Tessera-Kopf-/Seitenbild und -Symbol ## Verification - `cargo fmt --check && cargo check && cargo clippy && cargo test --lib` (apps/desktop/src-tauri): grün, 5/5 Tests - `pnpm --filter @tessera/web exec vitest run`: 417/417 Tests grün (63 Dateien) - `pnpm --filter @tessera/web type-check`: grün - nsis-Schema-Prüfung (node gegen `NsisConfig.properties`/`NSISInstallerMode`): OK - `magick identify`: `nsis-header.bmp BMP3 150x57`, `nsis-sidebar.bmp BMP3 164x314` - `git diff --name-only 98fad86 HEAD` deckt sich exakt mit `files_modified` aus dem Plan-Frontmatter; kein Docker-Build, kein `tauri build`, kein `git push`. ## Self-Check: PASSED - FOUND: apps/desktop/src-tauri/src/lib.rs (with_desktop_marker, update_labels, mod tests) - FOUND: apps/web/src/middleware.ts (withDesktopCookie) - FOUND: apps/web/src/lib/desktop-client.ts - FOUND: apps/web/src/components/desktop/desktop-context-menu-guard.tsx - FOUND: apps/desktop/src-tauri/icons/nsis-header.bmp, nsis-sidebar.bmp - FOUND commit 5bdabf5, d9b94bd, 2cd4adc in `git log --oneline`