Commit Graph
10 Commits
Author SHA1 Message Date
Mohamed Boudra e1c769c018 Make password-protected daemons work across local and remote connections (#5393)
* feat(auth): authenticate daemon clients through hello

Give local CLI and desktop clients a per-run credential while remote clients send the host password inside the protocol. Keep relay passwordless admission for this mobile release so existing saved hosts keep working until the follow-up enforcement release.

Move password recovery for saved hosts into host settings and keep pairing credentials in the add flow. Include isolated web QA evidence for both flows.

* fix(auth): preserve Hub bootstrap and local credential expectations

Hub-owned sockets already carry admission; keep their hello handling synchronous through session bootstrap while resolving credentials asynchronously for ordinary sockets. Keep the resolver out of lightweight configuration imports.

Update CLI expectations for same-home credentials, let a rejected connection yield to another usable connection, and clear pairing secrets when add-flow targets change.

* fix(pairing): retain passwords across edits to the same target

Track the last valid pairing host while a URI is edited. This preserves an entered password for whitespace and partial edits but clears it when a different host becomes the target.

* test(auth): align local credential checks across platforms

Expect the CLI to authenticate through the credential in its selected home, and verify POSIX file modes only where Node exposes them.

* feat(app): move host password into a settings row with a modal

The host page rendered an always-visible password form above Name on every
host. Replace it with a Password row under a Security section below
Appearance; tapping it opens a modal with Save and, when a password is saved,
Clear. The connection-error callout keeps its guidance and gains a Set
password button that opens the same modal. Drop the unused
pairing.hostPassword body/reopen/saveError strings.

* chore: remove committed QA screenshots

QA evidence stays out of the repository; the PR body describes it in words.

* feat(app): keep the host password out of the host page

The saved password is connection data, entered only when a host is added. A
Password setting on the host page reads as the daemon's own password, so the
row, modal, and callout button are gone. A rejected host shows the daemon's
reason with guidance to remove the host and add it again with the password.
useHostMutations no longer exposes setHostPassword; relay imports still set it
inside the runtime.

* feat(app): show host connection errors in an error alert

HostConnectionError renders the existing Alert with the connection error as
its title. Auth rejections add the re-add guidance as the description; other
errors show the title only. The Overview and Connections pages share it.

* style(app): soften alert borders to half-opacity accent

* feat(app): size alerts on the button scale

Alert takes a size prop (xs/sm/md/lg, default md) whose geometry lives next to
the button's in control-geometry: one font size for title and description, the
button icon size centered on the first text line, button padding and radius,
and a one-line alert as tall as the button of the same size. Consumers pick
sm among settings rows, cards, panels, and modals, and md when the alert is
the whole page or sheet state.

* style(app): roomier, rounder alerts with a tight title block

Alert sm padding returns to the original 12/16 and every size is at least
borderRadius.xl. Title and description sit a small gap apart with no line
height override. The icon slot carries a zero-width text strut in the alert's
font so the icon centers on the first line for titled, title-only, and
description-only alerts.

* refactor(app): align the alert icon with a centered lead row

Drop the zero-width strut. The icon and the alert's first text (title, else
description) share one row centered on each other; the description and actions
sit below, indented by the icon slot width plus gap so they start at the lead
text's left edge.

* refactor(app): drop the unused Alert icon override
2026-09-26 19:53:43 +02:00
Mohamed Boudra 772ff8d6f3 fix(desktop): preserve Linux sandboxing wherever the host allows it (#4447)
* fix(desktop): preserve Linux sandboxing wherever the host allows it

Chromium checks its Linux sandbox before main.js, while package installation probes run as root and miss AppArmor restrictions on desktop users. Choose the launch flags before exec and always install the SUID alternative for native packages. Test published artifacts as an ordinary user with namespaces both denied and allowed; never repair permissions in the smoke harness.

* fix(desktop): retain the Linux release build baseline

* fix(ci): allow canceled desktop smoke uploads to stop

* test(desktop): verify the installed RPM sandbox under AppArmor

* fix(ci): resolve packaged desktop dependencies before installation

* chore(desktop): keep QA evidence out of the repository
2026-09-11 09:05:26 +02:00
Mohamed Boudra 0110302b6f fix(daemon): keep lifecycle operations on the selected instance (#4575)
* fix(daemon): keep lifecycle operations on the selected instance

Restart reconstructed launch inputs and address fallback could redirect a home-selected shutdown to another daemon. Let supervisors publish bound endpoints, retain their worker restart contract, and share captured local lifecycle ownership between CLI and Desktop.

* test(daemon): verify bounded desktop readiness and cancellable artifacts

* test(cli): verify reload target hints and durable offline pairing

* test(daemon): align lifecycle fixtures with ownership and targeting

* fix(daemon): preserve reachability when status details time out

Provider discovery can outlast a status request after authentication succeeds. Keep local connection facts separate from unavailable details, while explicit remote queries retain their error outcome.

Migrate CLI and packaged Desktop fixtures to persistent managed configuration and explicit targets. Isolate generic Git observation from forge discovery and reuse disposable CLI homes on Windows.

* test(daemon): observe restart through the worker status RPC

The bounded CLI status observation may omit worker details while an authenticated connection remains healthy. Exercise the app-style restart through its full RPC and retain the replacement observation, with a real slow provider probe covering the distinction.
2026-09-11 08:33:22 +02:00
Mohamed Boudra 9e90b86afa Restore reliable macOS desktop updates (#4322)
* fix(desktop): restore macOS app updates

Electron 41's Squirrel helper can leave the update handoff dormant on current macOS, so Paseo quits cleanly but relaunches the old bundle. Electron 44 wakes ShipIt through its XPC service.

Include updater lifecycle events and ShipIt state in app diagnostics so future handoff failures identify the current version, target version, cache paths, and installer output.

* fix(desktop): harden updater diagnostics

Keep each ShipIt file's evidence available when another read fails, carry the service-selected version into updater lifecycle logs, and make clean workspace installs resolve the Electron runtime used by desktop tests.

* refactor(desktop): name updater install options

* refactor(desktop): name updater log payloads

* refactor(desktop): name clipboard payload

* fix(desktop): surface updater lookup failures

* test(desktop): await guest focus transition

* fix(desktop): guard macOS update compatibility

* test(release): validate desktop manifests before publish

* test(desktop): await populated daemon pid file
2026-09-04 22:17:39 +02:00
Mohamed Boudra ccb668b3b4 Improve sidebar workspace readability and host identity (#2790)
* fix(app): align turn footer actions

Keep running-turn actions in the same position as completed-turn actions and use the shared small icon size for both copy and fork controls.

* feat(app): improve sidebar workspace identity

Make dense sidebar workspace rows easier to scan and let each device control how connected hosts are identified.

* fix(app): keep host badges readable

Use a compact display menu and keep identity color on the host icon so translated controls fit and badge text retains standard contrast.

* fix(app): announce selected sidebar badge mode

* fix(app): retain icon-only host names for screen readers

* fix(app): name hoisted workspace rows

* fix(app): retain host identity in workspace labels

* fix(app): retain workspace status in row labels

* fix(app): defer host appearance until identity resolves

* fix(app): serialize host appearance writes

* fix(app): serialize host registry writes

* fix(app): bound sidebar host badge labels

* test(app): match workspace status labels

* fix(app): consolidate sidebar identity behavior

* test(app): assert status grouping behavior

* fix(app): keep sidebar row actions accessible

* fix(app): stabilize optimistic message layout
2026-08-02 16:58:20 +02:00
Mohamed Boudra 1977d330ed Reduce workspace, agent, and chat sync traffic (#2028)
* feat(sync): keep live data scoped and current

Only viewed chats receive live timeline rows, while directory state now uses one subscribed bootstrap followed by ordered deltas. Legacy clients and daemons retain their existing behavior through centralized compatibility gates.

* fix(sync): preserve selective delivery boundaries

Keep selective timeline capability app-owned, union viewed sets across shared sockets, and reconcile directory side effects from accepted state. Visibility and archive suppression now follow their existing authoritative boundaries.

* test(app): align browser fixtures with runtime contracts

* fix(sync): preserve mixed-client delivery guarantees

* fix(sync): finish paged history before advancing

* fix(sync): replay live deltas after refresh failures

* test(server): model socket capability lookup

* test(app): use platform shortcut for split-pane coverage

* fix(app): keep hidden timelines dormant

* test(app): normalize split-pane shortcut setup

* fix(app): preserve sync state across retries

* fix(app): preserve background sync state across races

* fix directory bootstrap reconciliation edge cases

* fix selective timeline compatibility races

* fix superseded directory sync races

* fix(sync): centralize directory replica ordering

Own agent and workspace refresh transactions in HostRuntime so reconnect epochs, buffered updates, and lifecycle invalidation share one ordering boundary. Route timeline metadata and mixed-capability stream delivery through their authoritative runtime sources.

* fix(app): keep timeline requests runtime-scoped

* fix(app): close directory bootstrap races
2026-07-17 17:03:34 +02:00
Mohamed Boudra 6aba0370ae Make remote daemon update failures actionable (#2120)
* fix(settings): show daemon update failures

React Native web ignores Alert.alert, so failed remote updates reset to an enabled button without any user-visible explanation. Keep updater progress and failure as explicit rendered state, including the daemon's error, and cover the real browser-to-daemon failure path.

* test(settings): harden daemon update regression

* fix(settings): disable Desktop-managed daemon updates

Desktop-bundled daemons advertised npm self-update even though the install-origin checks always rejected it. Report Desktop ownership to clients, render actionable guidance, and refuse stale requests before touching npm.
2026-07-16 21:04:31 +08:00
Mohamed Boudra 5e2a8b6633 Make help easier to find and cloned workspaces open reliably (#2045)
* feat(app): add sidebar help and support menu

Give users a single place to run diagnostics, find shortcuts, and reach the support channels. Share one global diagnostic sheet between Settings and the sidebar so both entry points collect the same report.

* fix(app): keep cloned workspace navigation atomic

A newly merged clone flow still used the previous navigation signature and opened its draft tab separately. Route the cloned workspace and its draft target through the unified navigation command so attention selection cannot replace the intended tab.

* test(app): harden sidebar help coverage

Accept both the Discord invite URL and its canonical redirect, assert placement through real element geometry, and remove an unnecessary diagnostic-host callback.

* test(app): cover support redirect variants

Keep the help-menu E2E stable across prerelease versions and the valid redirect forms returned by Discord and GitHub.
2026-07-14 00:02:53 +08:00
Mohamed Boudra f21c997b17 Include desktop app logs in diagnostics (#1914)
* fix(diagnostics): include desktop app logs

Settings diagnostics now collect the Electron main-process log separately from daemon.log so desktop startup and environment-probe failures are included in app reports.

* refactor(desktop): share log tail reader

* fix(diagnostics): surface desktop app log read errors

* refactor(diagnostics): tighten desktop report API
2026-07-06 17:50:45 +02:00
Mohamed Boudra 26f169866f Add app diagnostic report (#1728)
* feat(diagnostics): add app diagnostic report

* fix(diagnostics): guard app diagnostic runs

* fix(diagnostics): include websocket runtime metrics

* fix(diagnostics): type websocket metric snapshot

* fix(diagnostics): include daemon shell env

* fix(loop): make stop cancellation test deterministic
2026-06-25 23:20:52 +08:00