20 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, user_setup, estimate, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | user_setup | estimate | must_haves | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 18-desktop-client-fertigstellen | 05 | execute | 3 |
|
|
false |
|
|
|
Purpose: D-04, D-05, D-06 und D-16 aus 18-CONTEXT.md; Erfolgskriterium 1
(bis auf den Release-Anhang, der erst beim naechsten Freigabe-Tag sichtbar
wird — der Upload-Pfad selbst ist in 18-02 gebaut und per Probelauf geprueft).
Output: Erweiterter Job desktop, gruener Pipeline-Lauf mit beiden Dateien,
Beta-Abbilder mit Paketen.
Rollen: Der Executor pusht nie. Der Orchestrator pusht (git push; die
Push-Adresse zeigt auf localhost:3002), beobachtet den Lauf in Gitea und
meldet Status und Protokollauszug zurueck. Der Executor liest, behebt,
committet.
Artifacts this phase produces
Dieser Plan: .gitea/workflows/ci.yml (Schritte "Windows-Werkzeuge",
"Windows-Installer bauen (Cross-Bau)", erweiterte Cache-Pfade, Einsammeln
mit --require linux,windows); bei Bedarf Korrekturen an
.gitea/scripts/desktop-collect.sh, .gitea/scripts/publish-release.sh
(GITEA_API-Umgehung) und apps/desktop/src-tauri/Cargo.toml
(rustls-tls-Ausweichlösung). Gesamtliste der Phase: siehe 18-01-PLAN.md.
<execution_context> @$HOME/.claude/gsd-core/workflows/execute-plan.md @$HOME/.claude/gsd-core/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/18-desktop-client-fertigstellen/18-CONTEXT.md @.planning/phases/18-desktop-client-fertigstellen/18-RESEARCH.md @.planning/phases/18-desktop-client-fertigstellen/18-01-SUMMARY.md @.planning/phases/18-desktop-client-fertigstellen/18-02-SUMMARY.md @.planning/phases/18-desktop-client-fertigstellen/18-04-SUMMARY.md@.gitea/workflows/ci.yml @.gitea/scripts/desktop-collect.sh @.gitea/scripts/publish-release.sh @apps/desktop/src-tauri/Cargo.toml
Task 1: Windows-Cross-Bau in den Job desktop einbauen Reine Workflow-Schritte; Rueckbau ist ein Commit, kein Zustand ausserhalb des Runners ausser dem Cache. .gitea/workflows/ci.yml .gitea/workflows/ci.yml (Job desktop aus 18-02), .gitea/scripts/desktop-collect.sh (Windows-Zweig: Bundle-Pfad und Zielname), .planning/phases/18-desktop-client-fertigstellen/18-RESEARCH.md (Abschnitte "Pattern 1", "Standard Stack: Installation", "Common Pitfalls 2-5", "Open Questions 2-3"), .planning/phases/18-desktop-client-fertigstellen/18-CONTEXT.md (Abschnitt "Specific Ideas": Runner 8 Kerne/15 GB, nacheinander im selben Job) Im Job `desktop` (Datei `.gitea/workflows/ci.yml`) folgende Aenderungen, Schrittnamen deutsch:- Schritt "Systemabhaengigkeiten": die apt-Liste um
lld llvm clang nsiserweitern (alle vier am 2026-09-16 im Runner-Abbild perapt-cache policybestaetigt: lld/llvm/clang 18, nsis 3.09). - Neuer Schritt "Windows-Werkzeuge" nach "Rust-Toolchain":
rustup target add x86_64-pc-windows-msvcundcommand -v cargo-xwin >/dev/null 2>&1 || cargo install --locked cargo-xwin(Legitimitaetspruefung in RESEARCH:OK, rust-cross/cargo-xwin, 0.23.1). - Schritt "Cargo-Zwischenspeicher":
pathum~/.cargo/bin/cargo-xwin,~/.cache/cargo-xwin(Windows-SDK-Ablage von cargo-xwin, mehrere hundert MB, soll nur einmal geladen werden) und~/.local/share/tauri(NSIS-Plugins, die der Tauri-Bundler beim ersten Windows-Bau laedt) erweitern. - Schritt "Alte Bundles entfernen": zusaetzlich
rm -rf apps/desktop/src-tauri/target/x86_64-pc-windows-msvc/release/bundle. - Neuer Schritt "Windows-Installer bauen (Cross-Bau)" nach dem
AppImage-Schritt (nacheinander, ein Job, ein Cache — CONTEXT "Specific
Ideas"):
pnpm --filter @tessera/desktop exec tauri build --runner cargo-xwin --target x86_64-pc-windows-msvc --bundles nsis. - Schritt "Pakete einsammeln":
--require linux,windows. - Kopfkommentar des Jobs: zwei Saetze zum Cross-Bau und zum Grund, warum die Version rein numerisch bleibt (Pitfall 2).
Keine -j-Begrenzung und keine CARGO_BUILD_JOBS-Vorgabe im ersten Anlauf;
beides ist eine Ausweichlösung der Schleife (Task 3), falls der Runner den
Speicher ausschoepft. desktop-collect.sh braucht keine Aenderung, wenn der
Windows-Zweig aus 18-01 (desktop-collect.sh) den Pfad
target/x86_64-pc-windows-msvc/release/bundle/nsis/*.exe bereits kennt —
pruefen, sonst nachziehen.
<acceptance_criteria>
- grep -c 'cargo-xwin' .gitea/workflows/ci.yml ergibt mindestens 3 (Install, Cache-Pfad, Bauschritt).
- grep -c -- '--target x86_64-pc-windows-msvc --bundles nsis' .gitea/workflows/ci.yml ergibt 1.
- grep -c 'desktop-collect.sh --require linux,windows' .gitea/workflows/ci.yml ergibt 1; grep -c 'desktop-collect.sh --require linux$' .gitea/workflows/ci.yml ergibt 0.
- Die apt-Zeile enthaelt nsis, lld, llvm und clang (grep -E 'lld llvm clang nsis|nsis' .gitea/workflows/ci.yml).
- grep -c 'x86_64-pc-windows-msvc/release/bundle/nsis' .gitea/scripts/desktop-collect.sh ergibt mindestens 1.
- sh -n .gitea/scripts/desktop-collect.sh endet mit 0.
</acceptance_criteria>
cd /home/vicolab/projects/tessera-ctl && test "$(grep -c 'cargo-xwin' .gitea/workflows/ci.yml)" -ge 3 && grep -q -- '--target x86_64-pc-windows-msvc --bundles nsis' .gitea/workflows/ci.yml && grep -q 'desktop-collect.sh --require linux,windows' .gitea/workflows/ci.yml && grep -q 'nsis' .gitea/workflows/ci.yml && grep -q 'x86_64-pc-windows-msvc/release/bundle/nsis' .gitea/scripts/desktop-collect.sh && sh -n .gitea/scripts/desktop-collect.sh && node -e "const y=require('fs').readFileSync('.gitea/workflows/ci.yml','utf8');const d=y.indexOf('\n desktop:'),p=y.indexOf('\n publish:');if(d===-1||p===-1||d>p)process.exit(1);const job=y.slice(d,p);if(job.indexOf('--bundles appimage')>job.indexOf('--bundles nsis'))process.exit(2)" && echo WINDOWS-STEPS-OK
<fails_when>Ein Kennzeichen fehlt, das Einsammeln fordert Windows nicht, das Sammel-Skript kennt den NSIS-Pfad nicht, oder der Windows-Schritt steht vor dem AppImage-Schritt (Exit 2) — WINDOWS-STEPS-OK fehlt.</fails_when>
Der Job desktop installiert Windows-Werkzeuge, baut nach dem AppImage den
NSIS-Installer per Cross-Bau, cached SDK und NSIS-Plugins und sammelt beide
Dateien ein. Commit liegt bereit fuer den Push.
Zurueckmelden — je nach Ausgang:
Gruen: Aus dem Job desktop, Schritt "Pakete einsammeln", die beiden
Ausgabezeilen (windows: Tessera-Setup-1.1.0-beta.{sha}.exe (…) und
linux: Tessera-1.1.0-beta.{sha}.AppImage (…)), dazu Status des Jobs
publish (gruen) und die Zeile mit den gepushten Etiketten.
Rot: Name des gescheiterten Jobs und Schritts sowie die letzten rund 60
Protokollzeilen dieses Schritts (mit der eigentlichen Fehlermeldung — bei
Rust die Zeilen ab error: bzw. error[E…], bei apt die Zeile E:, bei
curl den HTTP-Code und die Antwort). Diese Runde zaehlt (Runde 1 von
hoechstens 3).
Der Lauf ist gruen; Schritt "Pakete einsammeln" nennt genau eine .exe und genau ein .AppImage; der Job publish hat die Beta-Abbilder gepusht. Der Executor prueft nach der Rueckmeldung zusaetzlich git status --porcelain (leer) und dass git log -1 --format=%H dem vom Orchestrator genannten Lauf-Commit entspricht.
Antworte mit "gruen" plus den beiden Dateizeilen — oder mit "rot" plus Job, Schritt und Protokollauszug.
Der Lauf ist gruen; Schritt "Pakete einsammeln" nennt genau eine .exe und genau ein .AppImage; der Job publish hat die Beta-Abbilder gepusht.
Rueckmeldung liegt vor. Bei "gruen" ist der Plan fertig (Task 3 entfaellt).
Bei "rot" geht es mit Task 3 weiter.
Bekannte Fehlerbilder und die jeweils vorgesehene Aenderung (in dieser Reihenfolge pruefen):
| Signatur im Protokoll | Ursache | Aenderung |
|---|---|---|
E: Unable to locate package … |
Paketname falsch/umbenannt | Namen mit docker run --rm gitea/runner-images:ubuntu-latest sh -c 'apt-get update -qq; apt-cache policy {name}' pruefen und in der apt-Zeile korrigieren |
The system library '…' required by crate '…' was not found (pkg-config) |
dev-Paket fehlt | fehlendes lib…-dev in die apt-Zeile aufnehmen (Pitfall 5) |
failed to run custom build command for openssl-sys beim Ziel x86_64-pc-windows-msvc |
TLS-Backend zieht OpenSSL fuer das Windows-Ziel | in Cargo.toml reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] } (Pitfall 3), lokal cargo check, Cargo.lock mit committen |
makensis: not found / NSIS … not installed |
NSIS fehlt im PATH | nsis in der apt-Zeile pruefen; sonst Pfad /usr/bin/makensis per which makensis im Protokoll ausgeben lassen |
failed to download NSIS plugin / nsis_tauri_utils |
Netz/GitHub | gleicher Stand, erneut pushen (leerer Commit ci(desktop): Runde N — erneuter Lauf) |
llvm-rc / rc.exe / winres / embed-resource |
Ressourcen-Compiler nicht gefunden | sudo ln -sf /usr/bin/llvm-rc-18 /usr/bin/llvm-rc im Schritt "Windows-Werkzeuge" oder env: RC: llvm-rc-18 am Bauschritt |
xwin / Failed to download / manifest beim ersten Cross-Bau |
Windows-SDK-Download | erneut pushen; falls wiederholt: env: XWIN_ARCH: x86_64 und XWIN_CACHE_DIR: ${{ github.workspace }}/.xwin-cache (dann .xwin-cache in die Cache-Pfade) |
optional build metadata in app version must be numeric-only |
Version nicht numerisch | git describe-Ausgabe im Protokoll pruefen; desktop-version.sh haette abbrechen muessen — Regex im Skript nachziehen |
genau eine Datei erwartet (Sammel-Skript) |
Bundle-Pfad oder Altbestand | Pfad mit find apps/desktop/src-tauri/target -name '*.exe' -path '*bundle*' im Protokoll ermitteln und im Skript anpassen; Aufraeum-Schritt pruefen |
Cache service responded with 4xx/5xx / Failed to save / fail-on-cache-miss obwohl gespeichert |
actions/cache-Version vs. Cache-Server | actions/cache/save@v3 und actions/cache/restore@v3 (Open Question 3); bleibt es rot: target aus den Cache-Pfaden nehmen (zu gross) |
Killed / signal: 9 / memory waehrend rustc |
Speicher | env: CARGO_BUILD_JOBS: 4 am Job (CONTEXT "Specific Ideas") |
| Job-Zeitueberschreitung | Baudauer plus Cache-Sicherung | target aus den Cache-Pfaden nehmen, ~/.cargo/registry und xwin-Ablage behalten |
docker build scheitert an COPY desktop-dist |
Verzeichnis fehlt im Kontext | Cache-Restore-Pfad und test -f-Schritt in publish pruefen |
Release-Upload 413 (nur bei Tags) |
Proxy-Groessengrenze vor git.vicolab.de |
am Release-Schritt env: GITEA_API: http://172.18.0.1:3002/api/v1 (Host-Adresse, ueber die der Runner auch seinen Cache-Server erreicht) |
Release-Upload 400 mit "file type" (nur bei Tags) |
Gitea [repository.release] ALLOWED_TYPES eingeschraenkt |
nicht im Repository loesbar — dem Nutzer melden (Server-Einstellung); Voreinstellung der Instanz laesst alle Typen zu (geprueft 2026-09-16) |
cargo clippy Fehler |
Code | Stelle beheben, cargo clippy lokal gruen |
Jede Runde im SUMMARY festhalten: Signatur, Ursache, Aenderung, Commit.
Trifft keine Signatur zu, die Ursache aus dem Protokoll ableiten und die
kleinste plausible Aenderung waehlen; im Zweifel zuerst mehr Protokoll
anfordern (z. B. RUST_BACKTRACE=1 oder --verbose am Bauschritt), statt
zu raten.
<acceptance_criteria>
- Jede Runde ist genau ein Commit mit Praefix ci(desktop): Runde N — (git log --oneline -5 | grep -c 'ci(desktop): Runde' entspricht der Rundenzahl).
- Nach jeder Aenderung: sh -n fuer geaenderte Skripte endet mit 0; bei Cargo-Aenderungen endet cargo check in apps/desktop/src-tauri mit 0.
- Es gibt nie mehr als drei Runden; nach der dritten roten Runde wird der Stand dem Nutzer vorgelegt statt weiter zu pushen.
- Am Ende: Task 2 hat "gruen" mit genau einer .exe- und einer .AppImage-Zeile gemeldet.
</acceptance_criteria>
cd /home/vicolab/projects/tessera-ctl && sh -n .gitea/scripts/desktop-collect.sh && sh -n .gitea/scripts/publish-release.sh && sh -n .gitea/scripts/desktop-version.sh && (cd apps/desktop/src-tauri && cargo check 2>&1 | tail -1 | grep -q Finished) && test "$(git rev-list --count --grep='ci(desktop): Runde' HEAD~6..HEAD)" -le 3 && echo ROUND-OK
<fails_when>Ein Skript hat einen Syntaxfehler, cargo check scheitert nach einer Cargo-Aenderung, oder es gibt mehr als drei Runden-Commits — ROUND-OK fehlt.</fails_when>
Der Orchestrator bestaetigt nach der letzten Runde einen gruenen Lauf mit beiden Dateizeilen (Task 2).
Ein gruener Pipeline-Lauf auf main mit Tessera-Setup-1.1.0-beta.{sha}.exe
und Tessera-1.1.0-beta.{sha}.AppImage im Schritt "Pakete einsammeln" und
gruenem publish; hoechstens drei dokumentierte Runden.
<threat_model>
Trust Boundaries
| Boundary | Description |
|---|---|
| Runner -> Internet (rustup, crates.io, Microsoft-SDK ueber xwin, NSIS-Plugins von GitHub) | Der Cross-Bau laedt Werkzeuge und das Windows-SDK aus dem Netz. |
| Runner-Cache -> Bau | Aus dem Cache wiederhergestellte Artefakte (SDK, target/) fliessen in das Paket ein. |
Gebautes .exe -> Anwender-PC |
Unsigniert; SmartScreen warnt (D-09). |
STRIDE Threat Register
| Threat ID | Category | Component | Severity | Disposition | Mitigation Plan |
|---|---|---|---|---|---|
| T-18-15 | Tampering | Werkzeugketten-Download (cargo-xwin, SDK, NSIS-Plugins) | medium | mitigate | cargo install --locked cargo-xwin (Lockfile des Werkzeugs), rustup von der offiziellen Adresse, SDK ueber cargo-xwin (prueft Microsoft-Manifest-Hashes), NSIS aus dem Ubuntu-Archiv; Tauri laedt seine NSIS-Plugins mit hinterlegten Pruefsummen. |
| T-18-16 | Tampering | Cache-Vergiftung (target/, xwin-Ablage) |
low | accept | Der Cache-Server laeuft nur lokal fuer diesen Runner (172.18.0.1), keine fremden Schreiber; Schluessel haengt am Cargo.lock-Hash. |
| T-18-17 | Repudiation | Iterationsschleife | low | mitigate | Jede Runde ist ein eigener Commit mit Ursache im Titel und im SUMMARY dokumentiert. |
| T-18-18 | Information Disclosure | Protokollauszuege (Token) | low | mitigate | Gitea maskiert Secrets im Log; publish-release.sh gibt das Token nie aus (T-18-03). |
| T-18-SC | Tampering | cargo install --locked cargo-xwin (crates.io) |
low | mitigate | Legitimitaetspruefung in RESEARCH: OK (rust-cross/cargo-xwin, seit 2022, 63k Downloads/Woche); kein [ASSUMED]/[SUS], keine Sperr-Freigabe noetig. |
| </threat_model> |
<success_criteria>
- Der Job
desktoperzeugt auf dem Linux-RunnerTessera-Setup-X.Y.Z[…].exeundTessera-X.Y.Z[…].AppImagein einem Lauf. - Der Lauf ist gruen;
publishhat Beta-Abbilder mit Paketen gepusht. - Die Iterationsschleife ist dokumentiert und endete spaetestens nach drei Runden. </success_criteria>