Skip to content
This repository was archived by the owner on Nov 14, 2026. It is now read-only.

feat(migrate): one-shot hq-sync → hq-desktop-app handoff (default-off feature) - #337

Closed
hassaans wants to merge 3 commits into
mainfrom
feat/migrate-to-hq-desktop
Closed

hassaans wants to merge 3 commits into
mainfrom
feat/migrate-to-hq-desktop

Conversation

@hassaans

@hassaans hassaans commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

One-shot migration build: hand legacy hq-sync users off to hq-desktop-app

Because hq-sync and hq-desktop-app use different updater signing keys, the Tauri updater can't
cross-grade between them (it rejects the other app's signature — confirmed in production). This ships a
normal hq-sync release that performs the handoff with its own code — a plain, minisign-verified,
atomic in-place bundle swap — which isn't subject to the updater's cross-key check.

Safety gate — default OFF

Everything is behind a migrate-to-hq-desktop cargo feature that is off by default, so merging this is a
no-op for every normal hq-sync build. Only the designated migration release is built with the feature on.

What it does (commands/migrate.rs, run once, a few seconds after launch)

  1. Skip if already migrated (marker in ~/.hq/menubar.json) + single-instance lock.
  2. Fetch the hq-desktop-app updater manifest; pick the darwin bundle (arch, universal fallback).
  3. Download it; minisign-verify against hq-desktop-app's embedded public key — abort on any mismatch
    (this is the supply-chain gate; the exact check that stops a wrong-key bundle).
  4. Validate the staged .app is launchable (Info.plist + runnable executable) BEFORE any destructive op.
  5. Atomic in-place swap (renamex_np RENAME_SWAP) preserving the bundle path; keep the old bundle as a
    ~60s rollback backup
    (detached self-cleanup) rather than deleting before relaunch is proven.
  6. Record the marker; relaunch. Same bundle id + ~/.hq ⇒ config, keychain, and sign-in carry over.

In the migration build, the legacy hard version-gate and soft updater are cfg-gated off so they can't
race the swap.

Verification

  • cargo check + cargo test green in both default and --features migrate-to-hq-desktop.
  • VM-proved end to end: installed the migration build, launched it → it downloaded, verified, swapped in
    place, and relaunched as hq-desktop-app 0.9.6, with seeded ~/.hq config preserved and the app syncing.
  • Includes an adversarial safety review; its two findings (never-brick + updater race) are fixed here.

Build the migration release with: pnpm tauri build --features migrate-to-hq-desktop (+ the usual
recall-symlink + sign steps). Rollout (cut the signed migration release, then raise the hq-pro hq-sync
minVersion to it) is deliberately not part of this PR.

hassaans added 2 commits July 7, 2026 23:24
Two fixes from the adversarial safety review:

1) Never-brick on a bad bundle: validate the staged .app is structurally
   launchable (Info.plist + a runnable Contents/MacOS executable) BEFORE the
   atomic swap, so a minisign-valid-but-malformed archive is rejected before any
   irreversible op. And keep the swapped-out OLD bundle as a rollback backup for
   ~60s (detached cleanup) instead of deleting it before relaunch is proven.

2) No updater race: in the migrate-to-hq-desktop build, do NOT start the hard
   version-gate or the soft updater — both replace the same .app via the Tauri
   updater and would race the one-shot migration swap. Only the handoff runs.

Adds a unit test for the launchability guard. cargo check + cargo test green in
both default and --features migrate-to-hq-desktop.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

The single 15s request timeout capped the whole request, so the ~90MB
hq-desktop-app bundle download aborted with 'error decoding response body' on any
link slower than ~6 MB/s (VM-observed: 15.17s at 6.3 MB/s — just over). Split the
timeouts: keep 15s for the small latest.json manifest, add a 20s connect-timeout
+ a 600s total timeout for the bundle download. Without this the handoff fails the
download for most real users (failing safe, but never migrating).
@hassaans

hassaans commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

Closing as part of an org-wide backlog cleanup. This has been open since 2026-07-07, more than two weeks, so it is being closed by age rather than on its merits.

This repository is archived, so this PR could not have been merged in any case. This is not a judgment on the work.

@hassaans hassaans closed this Sep 2, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant