docs: Desktop-App — Update in der App (Handbücher, CI-Secrets, CHANGELOG)
Tessera CI/CD / Lint & Type Check (push) Successful in 48s
Tessera CI/CD / Tests (push) Successful in 1m8s
Tessera CI/CD / Desktop-Pakete bauen (push) Successful in 7m56s
Tessera CI/CD / Build & Publish Images (push) Successful in 3m12s

- 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>
This commit is contained in:
2026-09-17 15:36:58 +02:00
parent 7004b5b020
commit 7479cb485f
5 changed files with 125 additions and 16 deletions
+62 -7
View File
@@ -606,7 +606,10 @@ Kanal, Version, Dateinamen, Größen und Prüfsummen.
`publish` kopiert die fertigen Pakete in das API-Abbild nach
`/app/desktop-dist/`, zusammen mit einer `manifest.json` (Version, Kanal,
Dateinamen, Größen, Prüfsummen). Auf dem Beta-Kanal tragen die Dateinamen
Dateinamen, Größen, Prüfsummen; seit der Update-Funktion zusätzlich
`updateVersion` – die Form, die der Client vergleicht, `X.Y.Z` auf Live und
`X.Y.Z-beta.g{commit}` auf Beta – sowie je Plattform die `signature` des
Pakets). Auf dem Beta-Kanal tragen die Dateinamen
zusätzlich den Suffix `-beta.{commit}`, zum Beispiel
`Tessera-Setup-1.1.0-beta.742fb5c.exe` und
`Tessera-1.1.0-beta.742fb5c.AppImage`; auf Live steht dort die reine Form
@@ -617,14 +620,23 @@ Kontrolle auf dem Server:
```bash
docker compose exec api ls -l /app/desktop-dist
curl -s https://{ihre-adresse}/api-proxy/desktop/latest
curl -si "https://{ihre-adresse}/api-proxy/desktop/update?target=windows&arch=x86_64&current=0.0.0&base=https://{ihre-adresse}"
```
`ls -l` zeigt die abgelegten Dateien samt `manifest.json`; die `curl`-Abfrage
liefert dieselben Angaben als JSON (Version, Kanal, je Plattform Dateiname,
Größe, Prüfsumme und relative Download-Adresse) – das ist genau die Antwort,
die auch die Anmeldeseite und die Einstellungsseite auswerten. Antwortet die
Abfrage mit `404`, fehlt entweder das Verzeichnis oder das Manifest; die
Web-Oberfläche blendet den Download-Link dann automatisch aus.
`ls -l` zeigt die abgelegten Dateien samt `manifest.json`; die erste
`curl`-Abfrage liefert dieselben Angaben als JSON (Version, Kanal, je
Plattform Dateiname, Größe, Prüfsumme und relative Download-Adresse) – das
ist genau die Antwort, die auch die Anmeldeseite und die Einstellungsseite
auswerten. Antwortet die Abfrage mit `404`, fehlt entweder das Verzeichnis
oder das Manifest; die Web-Oberfläche blendet den Download-Link dann
automatisch aus.
Die zweite Kontrollzeile stellt die Frage, die der Desktop-Client beim Start
stellt: `200` mit `version`, `url` und `signature` bedeutet, dass sich
installierte Clients von diesem Server aktualisieren können; `204` bedeutet,
dass für diese Plattform kein signiertes Paket vorliegt (zum Beispiel ein Stand
vor September 2026 oder ein Bau ohne Schlüssel). Für Linux `target=linux`
einsetzen.
### Release-Dateien in Gitea
@@ -635,6 +647,47 @@ vorhandene Datei gleichen Namens, statt einen zweiten Anhang anzulegen. Die am
Release hinterlegte Datei ist byteidentisch mit der im Abbild ausgelieferten;
die Prüfsumme (`sha256`) aus `manifest.json` gilt für beide gleichermaßen.
### Updates in der App und der Signierschlüssel
Seit September 2026 aktualisiert sich die Desktop-App per Klick im Menü des
Infobereich-Symbols. Beim Start fragt sie `GET /api-proxy/desktop/update`
und installiert ausschließlich Pakete, deren Signatur zu dem im Client
hinterlegten öffentlichen Schlüssel passt – ein manipuliertes oder fremdes
Paket wird abgelehnt, bevor irgendetwas installiert wird. Das ist die
Vertrauensbasis der Update-Funktion, nicht die Prüfsumme im Manifest.
Der **private Schlüssel** liegt nicht im Repository. Er existiert an zwei
Stellen:
- als Gitea-Secrets `TAURI_SIGNING_PRIVATE_KEY` und
`TAURI_SIGNING_PRIVATE_KEY_PASSWORD` (Repository → Einstellungen → Actions →
Secrets); nur die beiden `tauri build`-Schritte des Jobs `desktop` sehen
sie, die Skripte kennen den Schlüssel nicht;
- als Sicherung auf dem Entwicklungsrechner unter
`~/.tessera/desktop-updater/` (`tessera-updater.key`, `password.txt` und
der öffentliche Teil `tessera-updater.key.pub`).
**Sicherung:** Legen Sie die beiden Dateien zusätzlich an einem zweiten
sicheren Ort ab. Geht der private Schlüssel verloren, können bereits
installierte Clients kein Update mehr annehmen: Es muss ein neues
Schlüsselpaar erzeugt (`pnpm --filter @tessera/desktop exec tauri signer
generate -w <pfad>`), der öffentliche Teil in
`apps/desktop/src-tauri/tauri.conf.json` unter `plugins.updater.pubkey`
eingetragen und jeder Client einmal von Hand neu installiert werden.
Ohne die Secrets bricht der CI-Bau ab („A public key has been found, but no
private key"). `tauri build --no-sign` ist ausschließlich für lokale Proben
gedacht und im CI nicht vorgesehen – ein so gebautes Paket trägt keine
Signatur, und der Update-Endpunkt antwortet dafür mit `204`.
Windows legt bei jedem Update einen Ordner `%TEMP%\Tessera-{Version}-updater-…`
(rund 100 MB) an und räumt ihn nicht auf. Das ist kein Fehler; die Ordner
können jederzeit gelöscht werden.
Der Client erlaubt Updates in der App nur über `https`. Anwender mit einer
`http`-Adresse sehen im Menü den Hinweis „Update nur über https möglich" und
nutzen weiterhin den Weg über den Browser.
### Umgebungsvariablen
Für die Desktop-Auslieferung ist keine neue Pflichtvariable nötig.
@@ -652,3 +705,5 @@ Für die Desktop-Auslieferung ist keine neue Pflichtvariable nötig.
| Client meldet „Unter dieser Adresse antwortet kein Tessera-Server" | Anwender hat die interne API-Adresse statt der Web-Adresse eingetragen, oder `/api-proxy` ist vom Client-Rechner aus nicht erreichbar | Die im Anwenderhandbuch beschriebene Adresse verwenden (dieselbe wie im Browser); Netzwerk-/Firewall-Erreichbarkeit der Web-Adresse prüfen. |
| Windows zeigt die SmartScreen-Warnung | Erwartet – die App ist für den internen Gebrauch nicht signiert (D-09) | Kein Fehler; Anwenderhandbuch, Abschnitt „Installation unter Windows", beschreibt den Ablauf. |
| Beta-Paket nennt einen älteren Commit als das laufende Abbild (Dateiname `-beta.<Commit>`, Einstellungen → Desktop-App) | Erwartet: Desktop-App seit diesem Commit unverändert, Pakete aus dem Zwischenspeicher übernommen (Abschnitt „Wann gebaut wird …") | Kein Fehler. Soll dennoch neu gebaut werden, genügt eine Änderung unter `apps/desktop/` im nächsten Push. |
| Client meldet „Update fehlgeschlagen" | Download über den Proxy abgebrochen (Größengrenze/Zeitlimit, siehe zweite Zeile dieser Tabelle), oder die Signatur passt nicht – die Pakete stammen nicht aus dem CI-Bau mit dem aktuellen Schlüssel | Kontrollzeile `/api-proxy/desktop/update` (Abschnitt „Wo die Pakete im Abbild liegen"), den Pipeline-Lauf und die Proxy-Einstellungen prüfen. Der Anwender kommt über den Browser-Weg weiter. |
| `/api-proxy/desktop/update` antwortet dauerhaft `204`, obwohl Pakete da sind | Manifest ohne `signature`/`updateVersion`: Pakete aus einem Bau vor der Update-Funktion oder mit `--no-sign` | Eine Änderung unter `apps/desktop/` pushen bzw. den Tag neu bauen lassen; im CI prüfen, dass die Secrets `TAURI_SIGNING_PRIVATE_KEY`/`_PASSWORD` gesetzt sind (Abschnitt „Updates in der App und der Signierschlüssel"). |