54e691a4c9
Release desktop / bundle (push) Successful in 5m26s
tauri-plugin-updater resolves the download target as {os}-{arch}-{installer}
first (linux-x86_64-deb — the bundler stamps the installer type into the
binary, verified with `strings` on a local .deb) and only then bare
linux-x86_64. Our manifest carried only the bare key, pointing at the
AppImage. A .deb install therefore downloaded the AppImage, verified its
signature, then failed install_deb()'s is_deb check with
InvalidUpdaterFormat — after the download, before any relaunch. This, not
version drift or swallowed errors, is why v0.1.0→v0.1.6 never self-updated.
latest.json now carries linux-x86_64-deb, linux-x86_64-rpm (when built) and
linux-x86_64 (AppImage), each with its own .sig. A .deb update ends in a
polkit password prompt (pkexec dpkg -i) — the intended admin gate on a
root-installed package. README + wiki updated; wiki also records the v0.1.6
LIVE field verification.
Claude-Session: https://claude.ai/code/session_01FWncR69HgGPuei1dLrW3cU
80 lines
4.6 KiB
Markdown
80 lines
4.6 KiB
Markdown
# @parking/desktop — Tauri v2 kiosk shell
|
|
|
|
A **thin native desktop window** over the `@parking/web` SPA. It contains **no UI and no business
|
|
logic** of its own: the window renders the *same* web app the browser does, so the desktop and the
|
|
browser stay identical and never drift. Device/auth/ledger logic stays in `@parking/server`. See
|
|
`wiki/decisions/desktop-shell-tauri.md`.
|
|
|
|
## How the "same look & functionality" guarantee works
|
|
|
|
| | Source of the UI |
|
|
| --- | --- |
|
|
| **Dev** (`tauri dev`) | the window loads `http://localhost:5173` — the **`@parking/web` Vite dev server**. Edit a component in `apps/web` → HMR updates the desktop window live. |
|
|
| **Prod** (`tauri build`) | the window bundles `apps/web`'s built `dist/`. `beforeBuildCommand` rebuilds the SPA first. |
|
|
|
|
There is only one UI codebase (`apps/web`); this package just wraps it.
|
|
|
|
## Backend connection
|
|
|
|
The SPA talks to Fastify over HTTP/WS. In a browser that's same-origin (relative `/api`). In the
|
|
desktop build the bundled assets load from `tauri://localhost`, so set **`VITE_API_BASE`** (read at
|
|
web build time — see `.env.example`) to the appliance's Fastify origin, e.g.
|
|
`http://127.0.0.1:3000`. The CSP `connect-src` in `tauri.conf.json` is already allowed for that
|
|
origin, and the backend must include the Tauri origin in `WS_ALLOWED_ORIGINS` for the live feed.
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
pnpm --filter @parking/desktop dev # native window over the web dev server (HMR)
|
|
pnpm --filter @parking/desktop bundle # build the SPA + bundle the desktop app (.deb/.rpm/.AppImage)
|
|
```
|
|
|
|
> `build` is a **no-op** in this package so `turbo run build` stays fast — the real desktop bundle
|
|
> (compiles Rust, minutes long) is the explicit `bundle` script above.
|
|
|
|
Requires the Rust toolchain and (on Linux) WebKitGTK 4.1 + libsoup-3 dev libraries. Under WSL2 the
|
|
window needs a display (WSLg or an X server).
|
|
|
|
## Auto-update
|
|
|
|
Signed updates are built and published by `.gitea/workflows/release.yml` on a `vX.Y.Z` tag, mirrored
|
|
to the public `mca/public_releases` repo (this repo is private; the updater runs on offline-first
|
|
field appliances with no Gitea credentials, so its endpoint must be reachable unauthenticated —
|
|
see that workflow's header and `wiki/decisions/desktop-shell-tauri.md`). The updater config and
|
|
signing pubkey live in `tauri.conf.json`; the private signing key is held outside the repo, never
|
|
committed.
|
|
|
|
**The manifest carries one entry per installer type** (`linux-x86_64-deb`, `linux-x86_64-rpm`,
|
|
and bare `linux-x86_64` for AppImage). The updater picks the entry matching how the running app
|
|
was installed — a `.deb` install will only ever accept a signed `.deb`. Booths run the `.deb`,
|
|
so an in-app update ends in a **polkit password prompt** (`pkexec dpkg -i`): that is expected,
|
|
and it is the right gate — the package lives in `/usr/bin`, root-owned, and the operator is not
|
|
supposed to be able to replace it silently. Cancel the prompt and the app keeps running the old
|
|
version; the failure is logged to the server's Logs viewer.
|
|
|
|
## Release gate — run the REAL bundle locally before tagging
|
|
|
|
`tauri dev` loads the SPA from `http://localhost:5173`, a plain http origin. The shipped bundle
|
|
loads it from `tauri://localhost`, a *secure* custom-scheme origin — and every desktop-only bug
|
|
found in the field on 2026-09-03/04 (relative-URL DOMException, mixed content, missing WS
|
|
`Origin`, the reqwest-vs-webview cookie split, the WS handshake that can't carry the cookie)
|
|
depends on that difference. **Dev mode cannot reproduce any of them**, so "works in `tauri dev`"
|
|
carries no information about a release. Before pushing a `vX.Y.Z` tag:
|
|
|
|
1. `pnpm --filter @parking/server dev` (local backend; `.env` must have `COOKIE_SECURE=0` and
|
|
`tauri://localhost` in `WS_ALLOWED_ORIGINS`).
|
|
2. `pnpm --filter @parking/desktop bundle` and run the produced AppImage from
|
|
`src-tauri/target/release/bundle/appimage/` (WSLg is enough).
|
|
3. On the ConnectScreen enter `127.0.0.1:3000`, **Test** must say reachable, then **Save**.
|
|
4. Log in. The booth header must show **LIVE** (not "JASHTË LINJË") within a few seconds.
|
|
5. Perform one mutation (e.g. change your UI language) — it must succeed (proves CSRF).
|
|
6. Open Setup → Logs and confirm a `frontend`-sourced row from this desktop session exists
|
|
(proves the desktop log channel; historically it was silently 403'd).
|
|
|
|
Only then tag. If a release still fails in the field, the gap is in this list — fix the list.
|
|
|
|
## Not here (deliberately)
|
|
|
|
Kiosk lockdown (fullscreen/no-decorations) and launching Fastify from the shell are out of scope for
|
|
the scaffold — on the appliance Fastify runs as its own service and this shell connects to it.
|