diff --git a/apps/web/src/lib/desktop-updater.ts b/apps/web/src/lib/desktop-updater.ts index 67ebd2c..2860365 100644 --- a/apps/web/src/lib/desktop-updater.ts +++ b/apps/web/src/lib/desktop-updater.ts @@ -9,6 +9,17 @@ // and never tries to resolve the Tauri APIs. Offline-first: a failed check (no // network — the appliance is usually offline) is swallowed; updates only happen // when someone has brought the box online (e.g. a phone hotspot) on purpose. +// +// A release build's console.error is invisible with no way to attach devtools +// in the field (kiosk mode blocks the context menu; this WebKitGTK build's +// remote inspector doesn't answer standard discovery endpoints either — both +// confirmed dead ends 2026-09-03). logClient() ships straight to the +// server-side app_logs store regardless of the client's console-forward log +// level (that gate is meant for noisy console chatter, not this), so a real +// post-accept install failure is visible via wiki/concepts/app-logs.md / +// LogsViewer.tsx without needing a terminal or devtools at all. + +import { logClient } from "./logger.js"; /** True when running inside the Tauri webview (not a normal browser). */ function inTauri(): boolean { @@ -42,13 +53,24 @@ export async function checkForDesktopUpdate( // Download + install the signed update (signature verified against the // pubkey in tauri.conf.json), then relaunch into the new version. try { - await update.downloadAndInstall(); + await update.downloadAndInstall((progress) => { + logClient({ + level: "info", + message: `desktop update download progress: ${progress.event}`, + context: { kind: "desktop_update_progress", version: update.version, event: progress.event }, + }); + }); } catch (err) { // A real update WAS found and accepted — this is a genuine install // failure (bad signature, corrupted download, disk/permission issue), // not "offline". Surface it instead of silently reverting to the old // version with no explanation. - console.error("desktop update download/install failed:", err); + logClient({ + level: "error", + message: `desktop update download/install failed: ${err instanceof Error ? err.message : String(err)}`, + stack: err instanceof Error ? err.stack : undefined, + context: { kind: "desktop_update_install_failed", version: update.version }, + }); throw err; } const { relaunch } = await import("@tauri-apps/plugin-process"); @@ -56,7 +78,13 @@ export async function checkForDesktopUpdate( } catch (err) { // Offline / endpoint unreachable / no update server yet → ignore. The app // keeps running on the current version; checking again next launch. Still - // log it so a real install failure (rethrown above) isn't invisible. - console.warn("desktop update check/apply skipped:", err); + // log it (info, not error — this path is expected/normal far more often + // than it's a real problem) so a real install failure (rethrown above, + // logged as error) isn't lost among routine offline checks. + logClient({ + level: "info", + message: `desktop update check/apply skipped: ${err instanceof Error ? err.message : String(err)}`, + context: { kind: "desktop_update_skipped" }, + }); } } diff --git a/wiki/decisions/desktop-shell-tauri.md b/wiki/decisions/desktop-shell-tauri.md index 1560e3f..b4bb638 100644 --- a/wiki/decisions/desktop-shell-tauri.md +++ b/wiki/decisions/desktop-shell-tauri.md @@ -176,7 +176,8 @@ Per the user's choices — the operator **keeps OS access** (no fullscreen lockd `.env.example` documenting `tauri://localhost,http://tauri.localhost` as required) — even a correct Origin header is useless if the server's allowlist doesn't include it. Both fixed together; a `resources.toml` change still needs a Komodo sync + Stack redeploy to take effect on - a live booth, it isn't automatic from a git push alone. + a live booth, it isn't automatic from a git push alone — and see [[fleet-deployment-komodo]] for + a real ResourceSync-branch gotcha this exact fix ran into. - **`VITE_API_BASE` — desktop vs. browser (regression found + fixed 2026-09-03):** `apps/web/.env.production` (committed, shared by both builds) sets `VITE_API_BASE=` (empty) — this is correct for the **browser/booth** build (Fastify same-origin, stays relative) since commit diff --git a/wiki/decisions/fleet-deployment-komodo.md b/wiki/decisions/fleet-deployment-komodo.md index 86dc054..8192eb5 100644 --- a/wiki/decisions/fleet-deployment-komodo.md +++ b/wiki/decisions/fleet-deployment-komodo.md @@ -2,7 +2,7 @@ type: decision tags: [parking, deployment, fleet, komodo, netbird, offline-first, threat-model] sources: [] -updated: 2026-07-07 +updated: 2026-09-03 status: settled --- @@ -192,3 +192,32 @@ FILE is read from, each stack's `branch` picks its compose files, `TAG` picks th secrets even in the lab (blast radius). The lab box earned its keep immediately: it caught the USB close-cancel truncation, the printer/controller wizard gate, and the Periphery v2.2.0 root_directory default before any of them reached a real booth ([[appliance-provisioning]] §7a). + +## ResourceSync branch drift — the exact gotcha this page already warned about (2026-09-03) + +This page's own §"park-lab" note (2026-07-07) already spelled it out: *"the ResourceSync's own +branch only governs where the FILE is read from"* — independent of any `[[stack]]`'s own `branch` +field. It bit anyway. `resource-sync-park-systems` in Komodo Core was pointed at **`dev`**, while +`park-buzi` and `park-2` are `stage`-tier Stacks (`branch = "stage"`, pinned `TAG=stage-`, per +the promotion-tiers model above). `resources.toml` had been byte-identical on `dev` and `stage` +since park-buzi's Stack was first written, so this had **zero observable effect for months** — until +a desktop-app debugging session (see [[desktop-shell-tauri]]) landed 9 real commits on `dev` +(including a `WS_ALLOWED_ORIGINS` fix) that were never merged to `stage`, creating the first genuine +divergence between the two branches. + +**Symptom:** merged `dev` → `stage`, pushed, bumped `TAG` in `resources.toml` on `stage`, committed, +pushed — then destroyed + recreated the `park-2` Stack in Komodo Core and it STILL came back running +the old image. Every sync was silently re-reading `resources.toml` from `dev` (which still had the +stale `TAG`), overwriting the correct value just committed on `stage`. No error, no warning — the +sync just quietly did what it was configured to do, from the wrong branch. + +**Fix:** pointed `resource-sync-park-systems` at `stage` in Komodo Core's UI (Sync config → branch +field), then re-synced + redeployed `park-2` — confirmed via `/api/version` (previously 404, +proving a stale image; correctly 401-auth-gated after the fix, proving the new image + route exist). + +**Standing lesson, now written twice:** a `[[stack]]`'s promotion tier (which branch its own +`branch`/`TAG` fields track) and the ResourceSync resource's own git branch are **two independently +configured settings in Komodo Core — nothing enforces they agree**, and a mismatch is invisible +until the two branches' `resources.toml` actually diverge. **Check this FIRST** whenever a +redeploy doesn't pick up an expected `resources.toml` change, before assuming the change itself, +the CI build, or the deploy step is broken. diff --git a/wiki/log.md b/wiki/log.md index 42dc98f..d4ec173 100644 --- a/wiki/log.md +++ b/wiki/log.md @@ -2793,3 +2793,18 @@ get the real allowlist. Needs a Komodo sync + redeploy to reach a live booth, no Also confirmed the "update downloads then nothing happens" report was an older pre-fix build (v0.1.2) self-updating — expected, not a new bug; v0.1.3 carries the error-logging fix from the mixed-content commit and should surface a real error going forward. Full detail on [[desktop-shell-tauri]]. + +## [2026-09-03] fix | Update failures were invisible: console-forward gate blocked the error logging + +The desktop-updater.ts error logging added earlier this session used console.error/console.warn, +but logger.ts only forwards console output to the server when the client log level is debug/trace +(default: info) — so the "fix" never actually surfaced anything, and a real v0.1.3→v0.1.4 update +failure showed zero logs anywhere, sending debugging in circles (a WebKit remote-inspector attempt +via WEBKIT_INSPECTOR_SERVER also dead-ended — this build doesn't answer standard discovery +endpoints). Fixed by calling logClient() directly in desktop-updater.ts, unconditionally, bypassing +the console-forward gate entirely — a genuine post-accept install failure now always reaches +app_logs regardless of client log level. Also added download-progress logging. Separately: found +and fixed a real, pre-existing Komodo ResourceSync misconfig (resource-sync-park-systems pointed at +`dev`, not `stage`, silently reading resources.toml from the wrong branch for months with zero +effect until dev/stage first diverged today) — full writeup on [[fleet-deployment-komodo]], which +had already warned about exactly this gotcha back in 2026-07-07 and it happened anyway.