Skip to content

feat(t05-03): build unsigned offline CLI and desktop release candidates - #99

Merged
TheHalfMoon merged 9 commits into
mainfrom
feat/t05-03-offline-packaging-release-candidates
Sep 17, 2026
Merged

TheHalfMoon merged 9 commits into
mainfrom
feat/t05-03-offline-packaging-release-candidates

Conversation

@TheHalfMoon

@TheHalfMoon TheHalfMoon commented Sep 17, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds the flake product-command binary (identical src/main.rs to fehrest, proven functionally equivalent by a new parity test suite), per plan section 25's "flake is the new product command" requirement.
  • Closes a deferred T01-05 obligation: wires backup-run/backup-restore/vault-recover CLI commands over the already-reviewed crate::backup/crate::recovery library functions.
  • Builds the full section-25 packaging pipeline: CLI release archives (with a new genuinely user-facing docs/release/USER_GUIDE.md), CycloneDX SBOM generation, desktop NSIS/deb/dmg bundle builds, install/launch/update/uninstall qualification (vault-retention + no-network-on-launch proof), and a two-clean-build reproducibility check — all wired into a new 3-OS CI workflow (.github/workflows/t05-03-release-candidates.yml).
  • Every artifact is labeled UNSIGNED_DEVELOPER_RC. Per the Founder's ruling and this task's own acceptance criteria (plan section 25: "every unsigned candidate installs/runs/updates/uninstalls"), Windows/macOS/Linux signing and notarization credentials are recorded as UNAVAILABLE and deferred to T05-04, never fabricated or treated as blocking this task.

Full detail, including honest limitations (update/rollback tested as reinstall-over-existing since no second historical release exists yet; Linux offline-dependency-bundle not yet built; network-blocked-image approximated via connection-table observation): docs/evidence/flake-v1/T05-03/REPORT.md.

Test plan

  • cargo fmt --all -- --check / cargo clippy --all-targets --locked -- -D warnings / cargo test --locked --all-targets (379 tests) / cargo audit — all clean locally (Windows)
  • Desktop crate cargo fmt/clippy and frontend tsc --noEmit — clean locally
  • scripts/release/package_cli_archive.sh and scripts/release/generate_sbom.sh run and verified locally (Windows)
  • .github/workflows/t05-03-release-candidates.yml green on all three native platforms (CI)

🤖 Generated with Claude Code

https://claude.ai/code/session_017y9yraFkEzskx96yEgLPuG


Summary by cubic

Builds the unsigned release-candidate pipeline for the offline flake CLI and desktop app, keeping fehrest as the identical historical alias. Adds the flake binary, wires the previously deferred backup-run/backup-restore/vault-recover CLI commands, and produces Windows/macOS/Linux archives and installers labeled UNSIGNED_DEVELOPER_RC.

Release pipeline

  • Adds a 3-OS CI workflow that builds CLI archives, desktop bundles (NSIS/deb/dmg), CycloneDX SBOMs, and a two-clean-build reproducibility check.
  • Qualifies every artifact with install/launch/update/uninstall testing that proves vault retention; update is approximated as reinstall-over-existing since no prior release exists.
  • Signing and notarization credentials are recorded as UNAVAILABLE; code signing is deferred to T05-04.
  • CI runs surfaced fixes: release scripts now carry the executable bit; Windows bundles were narrowed to NSIS only (MSI rejects the project's version string); the macOS network check inspects only the launched process's own sockets; the Linux GUI launch runs under xvfb; and the Windows install test fails fast after ~10 minutes, with WebView2 registry state captured and Defender real-time scan disabled for that job.
  • The Windows installer hang was traced to MSYS mangling /S into S:/ so silent mode never ran; fixed with //S, keeping the bounded timeout and process-tree diagnostics as a safety net.
  • The workflow is green on all three platforms; the evidence report records the run links and the hang investigation.

Written for commit b364882. Summary will update on new commits.

Review in cubic

Adds the `flake` product-command binary (identical src/main.rs to
`fehrest`, proven functionally equivalent by a new parity test suite),
closes a deferred T01-05 obligation by wiring backup-run/backup-restore/
vault-recover CLI commands over the already-reviewed backup/recovery
library, and builds the full section-25 packaging pipeline: CLI release
archives with a new user-facing guide, CycloneDX SBOM generation,
desktop NSIS/deb/dmg bundle builds, install/launch/update/uninstall
qualification with vault-retention and no-network-on-launch proof, and
a two-clean-build reproducibility check -- all wired into a new 3-OS CI
workflow.

Per the Founder's ruling and this task's own acceptance criteria (plan
section 25: "every unsigned candidate installs/runs/updates/uninstalls"),
every artifact is labeled UNSIGNED_DEVELOPER_RC; Windows/macOS/Linux
signing and notarization credentials are recorded as UNAVAILABLE and
deferred to T05-04, not fabricated or treated as blocking this task.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017y9yraFkEzskx96yEgLPuG
@qodo-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing

@coderabbitai

coderabbitai Bot commented Sep 17, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 082244c7-98d9-444a-b4f9-dba0e50e406b


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

TheHalfMoon and others added 8 commits September 17, 2026 03:53
…undle targets

CI found two real bugs this development host's own Windows shell
couldn't surface:

- scripts/release/*.sh were committed as mode 100644 -- git on Windows
  does not track the executable bit the same way, so every direct
  `scripts/release/foo.sh` invocation in the CI workflow (no `bash`
  prefix) failed with "Permission denied" (exit 126) on macOS/Linux
  runners. Windows's own git-bash ignores the unix permission bit
  entirely, which is why this was invisible locally. Fixed via
  `git update-index --chmod=+x`.

- tauri.conf.json's bundle.targets "all" tried to build an MSI
  installer on Windows in addition to NSIS; msitools rejects this
  project's own `0.0.1-phase-t` version string ("optional pre-release
  identifier ... must be numeric-only ... for msi target"). Plan
  section 25 only ever asked for a Windows NSIS installer, not MSI, so
  narrowed targets to exactly ["nsis", "deb", "dmg"] rather than
  reformatting the version to satisfy a bundler this project was never
  going to ship.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017y9yraFkEzskx96yEgLPuG
…UI launch under Xvfb

Two more real CI-only bugs (this Windows development host cannot
surface either):

- The macOS job's whole-machine connection-table diff caught several
  outbound TLS connections to Apple IP ranges the instant any new
  unsigned .app was launched -- consistent with the OS's own
  Gatekeeper/OCSP-style check of an unrecognized app, not anything
  Flake's own process requested. Rewrote the check to inspect only the
  launched process's own open sockets (lsof -p / ss -p / netstat -ano
  filtered by pid), which is what the F05 "no runtime
  downloads/telemetry" claim actually needs -- not "nothing on the
  whole machine changed", which no real OS satisfies.

- The Linux job's GTK app launch failed outright ("Failed to
  initialize GTK backend") on the headless ubuntu-latest runner, which
  has no display server -- the same condition t04-06-cross-platform.yml
  already solved for its own native-launch smoke test via `xvfb-run`.
  Applied the same fix here, plus installing `xvfb` alongside the
  existing Linux Tauri system dependencies. Since xvfb-run wraps the
  real app in its own process, `$!` no longer names the wrapped app's
  own pid -- launch_and_check_no_network now re-resolves the actual
  running pid via `pgrep -f <binary basename>` before checking its
  sockets, on every platform (a no-op reconfirmation on macOS/Windows,
  where the launch was already direct).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017y9yraFkEzskx96yEgLPuG
…2 registry evidence

A prior run of desktop-bundle-install-test (windows-latest) hung 48+
minutes inside the NSIS installer's own bundled WebView2-runtime step
(cancelling it showed the installer's child process still alive),
versus ~5 minutes for the identical macOS/Linux jobs. Add a
step-level timeout-minutes so a recurrence fails in ~10 minutes with
a clear signal instead of silently consuming hours, and a Windows-only
diagnostic step recording the exact WebView2 registry state so the
next occurrence (if any) is root-caused from real runner data rather
than guessed. No change to install_test.sh's own logic or to any
acceptance criterion.
…ll test

Confirmed (via a registry diagnostic added in the prior commit) that
this runner's WebView2 Runtime registration IS present under the exact
key Tauri's NSIS template checks, ruling out the runtime-install/
elevation path as the cause of the observed hang -- both branches of
that template's WebView2 section compile to a no-op for this project
(no minimumWebview2Version is configured, so the template's own
compile-time guard excludes the elevation-requiring branch entirely).

Leading remaining explanation: offlineInstaller mode unconditionally
embeds the ~180 MB WebView2 offline runtime installer inside the NSIS
package regardless of whether it is reachable at runtime, producing a
large, unsigned executable with a nested embedded payload -- a shape
that commonly stalls Windows Defender's execution-time heuristic/
cloud-reputation scan on first launch on GitHub-hosted Windows
runners, invisibly to the launched process. Disabling real-time
monitoring changes only this CI job's own transient test environment,
never the shipped product, and does not weaken any T05-03 acceptance
criterion.
… of guessing

Two root-cause theories for the Windows install-test hang were checked
directly against the actual CI runner and ruled out: the runner's
WebView2 Runtime registration is present under the exact key Tauri's
NSIS template checks (so that template's runtime-install/elevation
path never runs), and disabling Windows Defender's real-time scan for
the job made no difference (still hung to the same 10-minute step
timeout). Guessing a third theory blind is not root-causing it.

Wrap each Windows install/reinstall/uninstall invocation in
run_windows_exe_with_diagnostics: it bounds the wait to 90s and, if
exceeded, dumps the full live process tree (via WMI) before killing
it, so the actual blocking child process is visible in the next CI
log instead of remaining a silent, unexplained hang. No change to
macOS/Linux logic or to any acceptance criterion.
…etection bug

The prior commit's run_windows_exe_with_diagnostics hand-rolled
backgrounding + polled `kill -0` to detect a hang. The very next CI run
showed this is unreliable under MSYS: `kill -0` on a backgrounded
native Windows GUI process can keep reporting "alive" (POSIX zombie-PID
semantics -- the slot isn't freed until something actually `wait`s it)
even after the real process already exited; that run's own `taskkill`
on the tracked pid immediately reported "process not found", confirming
the wrapper's own 90s "still running" verdict was a false positive, not
evidence about the installer.

Rewritten to use GNU `timeout` (present on this project's Windows CI
image, verified locally), which performs a real blocking wait on the
actual child and cannot exhibit this ambiguity. A background snapshot
of the live process tree still fires unconditionally partway through
the bound, harmless if the command already finished, so a genuine hang
is diagnosed from live data rather than a post-mortem guess. Verified
locally against both a fast-success and a genuine-timeout case before
pushing.
…ran non-silent

Confirmed via the process-tree diagnostic added in the prior two
commits: the actual argv NSIS received during the hang was
`Flake_..._x64-setup.exe S:/ /D=...`, not `/S /D=...`. MSYS bash
auto-converts a bare `/S`-shaped argument into a Windows drive-relative
path before the native child ever sees it, so silent mode was never
requested -- the installer launched its normal interactive GUI wizard
and waited forever for a click no headless CI session can provide.
This explains every observed symptom exactly (zero further script
output; the installer's own child process still alive when force-
cancelled after 48+ minutes) and neither of the two earlier theories
(WebView2 elevation, Defender scanning) did.

Fix: `//S`, MSYS's standard escape for this exact class of bug and
already used a few lines below for taskkill's own `/F /T /PID` flags.
Verified locally that a native process still receives the plain
`/S` it actually expects. The bounded timeout + process-tree
diagnostics from the prior two commits are kept as a defensive safety
net for any future CI hang, now with a correct (non-buggy) hang
detector.
… evidence report

Fills in the previously-empty CI results section with the actual green
run links and an honest account of the real defect found and fixed
during this task's own qualification (MSYS mangling /S into S:/,
causing the NSIS installer to run non-silent and hang forever waiting
for a GUI click no headless CI session can provide), including the two
ruled-out theories and the diagnostic wrapper's own bug that was found
and corrected along the way.
@TheHalfMoon
TheHalfMoon merged commit f4e919e into main Sep 17, 2026
22 checks passed
TheHalfMoon added a commit that referenced this pull request Sep 17, 2026
T05-03 merged as f4e919e (PR #99,
CI run 35182353415 green on Windows/macOS/Linux). Flips
T05-03_STATUS to COMPLETE, records its merge commit and CI run, and
advances ACTIVE_IMPLEMENTATION_UNIT/NEXT_DEPENDENCY_READY_UNIT to
T05-04 per the canonical build plan's sequential P05 DAG.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant