--- phase: quick-260922-frg plan: 01 subsystem: apps/desktop/src-tauri tags: [desktop, tauri, updater, tray, proxy, 401, tdd] status: complete requires: - "quick-260917-kgc (In-App-Updater, PendingUpdate, spawn_version_check)" provides: - "Update-Eintrag im Tray mit drei sichtbaren Endzustaenden, nie mehr stumm gesperrt" - "Statuscode-Diagnose nach Err(ReleaseNotFound) ueber eigene Anfrage" - "Wiederholte Update-Pruefung alle vier Stunden" - "Klick auf den Eintrag ohne abgelegtes Update prueft erneut" affects: - "apps/desktop/src-tauri/src/lib.rs" - "CHANGELOG.md" tech-stack: added: [] patterns: - "Fehlerzustand eines Hintergrund-Checks im Menuetext ausschreiben statt Eintrag stumm sperren" - "Zweite Diagnose-Anfrage nur fuer den Statuscode, wenn eine Bibliothek ihn verschluckt" - "Benachrichtigung ueber Mutex mit dem zuletzt gemeldeten Text entprellen" key-files: created: [] modified: - apps/desktop/src-tauri/src/lib.rs - CHANGELOG.md decisions: - "Proxy-Zugangsdaten werden NICHT in den Client eingebaut (T-FRG-03); der Grund wird angezeigt, die Behebung liegt am Proxy" - "Wiederhol-Thread als std::thread mit sleep statt tokio::time, damit kein neues Feature/Crate noetig ist" - "diagnostic_update_url liefert String statt Option: bei unparsbarer Adresse faellt sie auf api_url zurueck, gespeicherte Adressen sind ohnehin immer parsebar" - "report_check_failure und clear_check_notice als eigene Helfer, damit die drei Fehlerzweige in spawn_version_check kurz bleiben" metrics: duration: "ca. 20 min (11:05 bis 11:26 Uhr, 22.09.2026)" completed: 2026-09-22 actuals: tokens: 5600 tasks: 1 commits: 1 plan_head_before: ae36a22 --- # Quick-Aufgabe 260922-frg: Update-Eintrag im Tray nie mehr stumm ausgegraut Summary Der Update-Eintrag im Menue des Infobereich-Symbols zeigt jetzt in jedem Fall, was die Pruefung ergeben hat: ein Update, kein Update, oder den Grund des Fehlschlags (z. B. „HTTP 401“, wenn der Passwortschutz am Proxy die Anfrage abweist). Ein Klick auf den Eintrag prueft erneut, und die App prueft von selbst alle vier Stunden statt nur beim Start. Nur der http-Fall bleibt weiterhin dauerhaft gesperrt. ## Was sich fuer den Betrieb aendert Bisher konnte der Nutzer nicht unterscheiden, ob es kein Update gibt oder ob die Pruefung gescheitert ist — in beiden Faellen stand da grau „Update installieren“, und ohne Neustart der App wurde nie wieder geprueft. Genau das war auf dem Client gegen alpha passiert: der Nginx Proxy Manager antwortet auf die Update-Anfrage mit 401, das Updater-Plugin macht daraus stumm `ReleaseNotFound`, und der Eintrag blieb grau, obwohl alpha das Paket `1.2.0-beta.gc001a08` bereithielt. Jetzt steht in diesem Fall „Update-Prüfung fehlgeschlagen (HTTP 401) – erneut prüfen“ im Menue, und einmalig erscheint eine Benachrichtigung, die den Passwortschutz am vorgeschalteten Proxy als wahrscheinlichen Grund nennt und klarstellt, dass Anmeldung und Arbeiten in der App nicht betroffen sind. Den Passwortschutz selbst kann und soll der Client nicht umgehen; die Behebung liegt am Proxy (Ausnahme fuer `/api-proxy/desktop/*` oder Aufhebung des Schutzes fuer alpha). ## Umsetzung - **Konstanten:** `UPDATE_ITEM_DEFAULT` („Update installieren“) ist weg, ersetzt durch `UPDATE_ITEM_CHECKING` („Suche nach Updates…“, gesperrt waehrend der Pruefung) und `UPDATE_ITEM_NONE` („Kein Update verfügbar – erneut prüfen“, anklickbar). Neu `UPDATE_CHECK_INTERVAL = 4 h`. - **Reine Funktionen:** `check_failure_labels(Option)` liefert Menue- und Benachrichtigungstext (401/403 mit Proxy-Erklaerung, andere Codes neutral, `None` = keine Verbindung). `diagnostic_update_url` baut die Update-Adresse mit ersetzten Platzhaltern in genau der Kodierung von `update_endpoint`. - **Statuscode-Diagnose:** Bei `Err(ReleaseNotFound)` stellt `probe_update_status` dieselbe Anfrage einmal mit eigenem `reqwest`-Client (8 s Timeout, Muster `check_server`) und liest nur den Statuscode. Bei Verbindungsfehlern des Plugins (`Err(_)` sonst) keine zweite Anfrage. - **Entprellung:** `LastCheckNotice(Mutex)` als eigener `app.manage`-Typ; `report_check_failure` meldet nur einen abweichenden Text, `clear_check_notice` leert ihn nach `Ok(Some)`/`Ok(None)`. - **Wiederhol-Thread:** in `setup` einmal gestartet, `std::thread::spawn` mit `sleep(UPDATE_CHECK_INTERVAL)` in Schleife, liest die Adresse je Durchlauf frisch und ueberspringt, wenn `PendingUpdate` bereits ein Update haelt. - **Klick „update“:** `take()` wie bisher; ohne abgelegtes Update startet `spawn_version_check` mit der gespeicherten Adresse; ohne Adresse nichts. `open_download_page` bleibt nur im Fehlerpfad der Installation. - **Menuebau:** „Suche nach Updates…“ (gesperrt) mit gespeicherter Adresse, sonst „Kein Update verfügbar – erneut prüfen“ (aktiv). - **Changelog:** neuer erster Stichpunkt unter „Unveröffentlicht → Behoben“. ## TDD Gate Compliance **RED (nachgewiesen):** Die sieben neuen Tests wurden zuerst eingefuegt. `cargo test` brach mit neun Fehlern `E0425` ab — `cannot find function check_failure_labels`, `cannot find function diagnostic_update_url`, `cannot find value UPDATE_ITEM_CHECKING / UPDATE_ITEM_NONE / UPDATE_CHECK_INTERVAL`. Der Kompilierfehler zaehlt laut Plan als rot. **GREEN:** Nach der Umsetzung `cargo test`: 44 bestanden, 0 fehlgeschlagen (37 Bestandstests plus 7 neue). `is_update_newer`, `update_labels`, `release_labels`, `update_endpoint`, `spawn_update_install` unveraendert. **REFACTOR:** Zwei Helfer (`report_check_failure`, `clear_check_notice`) herausgezogen, damit die Fehlerzweige in `spawn_version_check` lesbar bleiben; der Kommentar bei `with_desktop_marker` nennt nicht mehr den alten Text „Update installieren“. ## Cargo-Ergebnisse (apps/desktop/src-tauri, lokal) | Schritt | Ergebnis | |---|---| | `cargo fmt --check` | sauber | | `cargo clippy` | 0 Warnungen, 0 Fehler | | `cargo test` | 44 passed, 0 failed | | `cargo build` (Debug) | erfolgreich, Systembibliotheken vorhanden | | `grep 'HTTP 401' CHANGELOG.md` | Treffer | ## Commit - `d73aad1` fix(desktop): Update-Eintrag nennt den Grund einer fehlgeschlagenen Pruefung, Klick prueft erneut, Pruefung alle 4 h — `apps/desktop/src-tauri/src/lib.rs`, `CHANGELOG.md` ## Deviations from Plan None - plan executed exactly as written. Einzige Ergaenzung ausserhalb der Aufzaehlung: der Doc-Kommentar bei `with_desktop_marker` verwies noch auf den entfernten Menuetext „Update installieren“ und wurde mitgezogen (reine Kommentar-Korrektur, kein Verhalten). ## Known Stubs Keine. ## Offen (fuer den Orchestrator, nach CI) - CI-Lauf: Job `desktop` muss neu bauen (apps/desktop beruehrt), Manifest im API-Abbild traegt den neuen Stempel. - Optional auf der Windows-Test-VM gegen alpha: neuer Client zeigt „Update-Prüfung fehlgeschlagen (HTTP 401) – erneut prüfen“ plus die Benachrichtigung mit der Proxy-Erklaerung. Damit der Client danach das Update tatsaechlich bekommt, muss der Proxy die Update-Anfrage durchlassen. ## Self-Check: PASSED - `apps/desktop/src-tauri/src/lib.rs` vorhanden und geaendert - `CHANGELOG.md` enthaelt die neue Zeile - Commit `d73aad1` in `git log` vorhanden