- LogoMark: gedrehte Signalkachel per Inline-Style fill: var(--primary, BRAND_YELLOW) statt festem fill-Attribut
- folgt damit der persoenlichen Akzentfarbe (applyAccentColor in auth-store.ts) in Kopfzeile, Seitenleiste und leerem Dashboard; ohne Nutzer (Anmeldeseite) gilt der CSS-Standard Markengelb
- brand.ts: Kommentar zu BRAND_YELLOW als Rueckfallwert ergaenzt
- tessera-logo.test.tsx: Kacheltest auf Inline-Style-Fuellung umgeschrieben (jsdom haelt var() in style.fill)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- STATE.md: Quick-Task-Zeile 260917-e15, Session Continuity, Last activity
- HANDOFF.json entfernt (einmaliges Uebergabe-Artefakt, in dieser Sitzung abgearbeitet)
- config.json: git.allow_default_branch_commits = true — Projekt committet
per branching_strategy "none" direkt auf main; ohne den Schalter blockiert
der Pre-Commit-Guard des Executors jeden Quick-Task
- SUMMARY des Quick-Tasks
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Die fuenf Icon-Dateien in apps/desktop/src-tauri/icons/ durch einen mit
der Tauri-CLI (tauri icon, Renderer resvg) erzeugten Satz ersetzt
- ImageMagick/MSVG hatte die gedrehte gelbe Kachel (transform rotate(12 51 21))
aus apps/web/src/app/icon.svg nicht gerendert, dadurch zeigte das Symbol
eine "1" statt des Tessera-T
- tauri.conf.json, Web-Code und Rust-Code unveraendert
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Bedienprobe des Users: Installer und Start liefen, dann schwarzes Fenster
"asset not found: index.html". Das Fenster "main" hatte keine Startseite,
Tauri nimmt dann index.html; die Erststart-Seite heisst setup.html (Altlast
aus Phase 6, in keinem echten Paket sichtbar geworden). CARGO_BUILD_JOBS=4,
weil 8 parallele rustc-Prozesse den gemeinsam genutzten Runner-Host (15 GB)
an die Speichergrenze brachten; Betriebshandbuch Kap. 10 ergaenzt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Mit dem Cargo-Zwischenspeicher wuerde ein einmal einkompilierter Stempel
sonst veralten und der Beta-Update-Hinweis dauerhaft erscheinen.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Alle vier Critical/Warning-Befunde aus 18-REVIEW.md sind behoben (CR-01
0d5c80f, WR-01 1b2f803, WR-02 579e24b, WR-03 a8964f1); die beiden Info-Befunde
bleiben laut Auftrag unbearbeitet (dokumentiert als uebersprungen). Status auf
clean gesetzt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
desktop-collect.sh vergibt fuer den Beta-Kanal (main) jedem Commit dieselbe
X.Y.Z-Version aus dem letzten Freigabe-Tag (D-07) -- der bisherige Vergleich
nur ueber `version` liess Nutzer zwischen zwei Tags nie eine neuere
Beta-Version sehen, obwohl manifest.json ein neues `commit`-Feld traegt.
build.rs bettet jetzt per `git rev-parse --short=7 HEAD` denselben
Commit-Stempel, den desktop-collect.sh fuer manifest.json schreibt, als
APP_COMMIT zur Kompilierzeit ein; lib.rs vergleicht bei channel == "beta"
zusaetzlich den Commit. Fuer den Live-Kanal bleibt es beim reinen
Versionsvergleich, D-07 (X.Y.Z in tauri.conf.json/Cargo.toml) bleibt
unveraendert. cargo check + cargo clippy -- -D warnings sind sauber.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Die CSP erlaubte 'unsafe-eval' und Wildcard-Quellen (connect-src/img-src/
font-src/style-src *), obwohl setup.html -- die einzige lokale Seite der App --
kein eval() nutzt, keine externen Schriften/Bilder laedt und ausschliesslich
ueber die Tauri-IPC-Bruecke (window.__TAURI__.core.invoke) mit dem Rust-Teil
spricht. Diese CSP gilt nur fuer vom App-eigenen Protokoll ausgelieferte
Seiten; nach save_server_url() navigiert das Hauptfenster auf die
Server-Adresse, und diese Navigation wird von der CSP der Zielseite selbst
bestimmt, nicht mehr von dieser Konfiguration. Verengt auf
default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self'
'unsafe-inline'; img-src 'self' data:; connect-src 'self'.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Die Zeichen-Whitelist /^[A-Za-z0-9._-]+$/ liess Namen wie ".." durch, weil
Punkt und Bindestrich erlaubte Zeichen sind -- path.join(desktopDistDir, '..')
loest aber in den Elternordner auf und unterlaeuft genau die Verteidigung in
der Tiefe (T-18-02), die diese Zeile laut Kommentar herstellen soll. Jetzt
werden "." und ".." explizit abgelehnt UND der aufgeloeste Pfad zusaetzlich
gegen desktopDistDir geprueft (haelt auch kuenftige Varianten ab, falls die
Whitelist anderswo wiederverwendet wird). Neue Testfaelle fuer manifest-Eintraege
namens "..", "." und "../manifest.json".
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Ein kaputter Plattform-Eintrag (z. B. fehlendes name-Feld oder ungueltiger
sha256) fiel bisher erst spaeter unbemerkt durch -- entry.name === undefined
wurde zu "undefined" gecoerct und als Dateiname gesucht. getManifest()
prueft jetzt jeden vorhandenen Plattform-Eintrag (name: string, size: number,
sha256: 64-stelliger Hex-String) und behandelt ein kaputtes Manifest wie ein
fehlendes (404 + Warn-Log), statt die kaputte Form durchzureichen.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Coverage-Block, Manuelle-Abnahme-Abschnitt mit Bedienprobe-Schrittfolge und
den zwei auf den naechsten Freigabe-Tag vertagten Punkten, Self-Check PASSED.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Neuer Abschnitt "Phase 18 — Desktop-Client fertigstellen" mit DESK-01..05
(DESK-01/02 aus Phase 6 fortgefuehrt, DESK-03..05 neu aus 18-CONTEXT.md)
- Traceability-Tabelle um fuenf DESK-Zeilen ergaenzt, Coverage-Satz aktualisiert
- Alle Gesamtlaeufe gruen: API 1086/1086, Web 365/365, beide Typpruefungen
fehlerfrei, cargo check Finished
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Betriebshandbuch: neues Kapitel 10 (Pipeline-Herkunft, Ablageort im Abbild,
Release-Anhaenge, DESKTOP_DIST_DIR, Fehlerbilder-Tabelle); Kapitel 9 um
Satz zu Desktop-Paketen im Freigabe-Tag ergaenzt
- CI/CD-Runbook: aus drei werden vier Jobs, Job desktop ausfuehrlich
beschrieben (Cross-Bau, Cache-Reihenfolge, Cache-vs-upload-artifact-
Begruendung), Fehlerbehebung um drei Unterabschnitte ergaenzt
(Job desktop, cache miss, Release-Upload 413)
- Entwicklungshandbuch: apps/desktop ist kein Grundgeruest mehr, neuer
Abschnitt "Desktop-App lokal bauen", Testabschnitt um vitest src/desktop
und cargo check/clippy ergaenzt
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Neues Kapitel "Desktop-App" (9 Unterabschnitte: Was es ist, Herunterladen,
Installation Windows/Linux, Erster Start, Infobereich/Beenden, Automatischer
Start, Neue Version, Fehlerbilder), Inhaltsverzeichnis um Punkt 8 ergaenzt
- CHANGELOG-Stichpunkt unter Unveroeffentlicht/Neu im Wortlaut von D-17
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Job desktop, Schritt "Rust pruefen": `cargo clippy` scheiterte mit
"'cargo-clippy' is not installed for the toolchain 'stable-x86_64-unknown-linux-gnu'"
(minimal-Profil enthaelt clippy nicht). `rustup component add clippy` direkt
nach der Toolchain-Installation ergaenzt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Baut nach dem AppImage zusaetzlich den Windows-Installer per Cross-Bau auf
dem Linux-Runner (cargo-xwin, NSIS aus dem Ubuntu-Paket), cached SDK und
NSIS-Plugins, und sammelt beide Dateien mit --require linux,windows ein.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- setup.html spricht nur noch über window.__TAURI__.core.invoke (kein
Modul-Import mehr, der im gebauten Client ohnehin scheiterte), prüft die
Adresse über check_server und speichert sie über save_server_url
- Sie-Form-Texte, Tessera-Zeichen als inline-SVG, Markengelb/-Olive,
keine vorbelegte Server-Adresse
- CSP ohne Fremdhost (unpkg.com entfernt), da nichts mehr von außen geladen wird
- Icon-Satz aus apps/web/src/app/icon.svg neu erzeugt (512, 128, 128@2x, 32,
ICO mit 16-256) statt der bisherigen flachen gelben Quadrate
- Versehentlich verschachteltes apps/desktop/src-tauri/apps/ entfernt
- Lokaler AppImage-Bau (Tessera-1.1.0.AppImage, ~103 MB) erfolgreich, von
desktop-collect.sh eingesammelt
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- tauri-plugin-opener@2 hinzugefügt (Legitimität in RESEARCH geprüft)
- Neue Rust-Kommandos check_server/save_server_url für die Erststart-Seite,
Adressen laufen über api_url() ausschließlich über /api-proxy/*
- Versionsprüfung gegen /api-proxy/desktop/latest statt /health/version,
schaltet den Tray-Eintrag "Update herunterladen" frei und benennt ihn um
- Tray-Menü: Öffnen · Update herunterladen · Autostart-Haken · Beenden,
echte Umlaute, Update-Eintrag öffnet die Download-Seite im Systembrowser
- capabilities/default.json: opener:allow-open-url für http/https
- cargo check und cargo clippy grün
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Neue Route /settings/general/desktop (DesktopSettingsPage)
- DesktopAppSettings: Version, zwei Primaerknoepfe mit Plattform-Symbol,
Dateiname/Groesse je Knopf, Beta-Kanal-Hinweis, vier erklaerende Saetze,
Hinweistext wenn keine Pakete hinterlegt sind
- Seitenleiste: Eintrag "Desktop-App" unter "Allgemein"
- de/en: settings.categoryDesktopApp, settings.desktop.*
- umlaut-dictionary.ts: "neuere" zur Allowlist ergaenzt (Rule 1 —
Waechter-Test brach an einer bereits korrekten Umlautschreibung, die
zufaellig die Buchstabenfolge "ue" enthaelt)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- apps/web/src/lib/desktop.ts: loadDesktopLatest (memoisiert, still bei
Fehler), desktopDownloadUrl, formatFileSize (lokalisierte MB-Werte)
- DesktopDownloadLinks: unauffaelliger Link-Block, rendert nichts ohne
Daten; Windows fuehrt, Linux als Kurzlink wenn beide Pakete vorliegen
- Anmeldeseite bindet den Block nach dem Formular ein (D-12)
- de/en: auth.desktopDownload.* ergaenzt
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- upload_asset() nach dem bestehenden GET-then-PATCH/POST-Idempotenzmuster:
GET .../assets -> vorhandene Datei gleichen Namens per DELETE entfernen ->
frisch per POST multipart (Feld attachment) hochladen
- Zweite Header-Datei HDR_AUTH (nur Authorization, kein JSON-Content-Type) fuer
den multipart-Upload; Token bleibt in Header-Dateien, nie als Argument (T-18-03)
- Nach Release-Anlage/-Aktualisierung wird jede Datei aus desktop-dist/manifest.json
hochgeladen; fehlt das Manifest bei einem Freigabe-Tag, bricht das Skript hart ab
- --dry-run listet zusaetzlich die geplanten Uploads aus dem Manifest, ohne Netzaufruf
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Neuer CI-Job desktop nach test, laeuft auf main und bei Tags v* (Systemabhaengigkeiten,
Rust-Toolchain per rustup, Cargo-Zwischenspeicher, Version setzen, cargo check/clippy,
alte Bundles entfernen, Linux-AppImage bauen, desktop-collect.sh --require linux,
Uebergabe per actions/cache/save mit Schluessel desktop-dist-${{ gitea.sha }})
- publish haengt jetzt an desktop (needs: desktop) statt an test, holt die Pakete per
actions/cache/restore mit fail-on-cache-miss: true und prueft das Manifest hart
- publish-images.sh bricht im echten Baupfad ohne desktop-dist/manifest.json ab
(zweites Netz gegen einen Cache-Fehlschlag, D-08/Pitfall 1)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
SUMMARY: 8 gruene Spec-Tests, Typpruefung fehlerfrei, lokaler Stack
liefert /desktop/latest und /desktop/download/linux auf Basislinie
1.1.0 aus. Ein Deviation-Eintrag (Rule 3): @Inject(DesktopService)
explizit noetig, da Vitest ueber esbuild ohne emitDecoratorMetadata
transpiliert.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>