Skip to content

fix: preserve service configuration and recover failed upgrades - #437

Open
peg wants to merge 10 commits into
stagingfrom
codex/preserve-service-launch
Open

fix: preserve service configuration and recover failed upgrades#437
peg wants to merge 10 commits into
stagingfrom
codex/preserve-service-launch

Conversation

@peg

@peg peg commented Sep 11, 2026

Copy link
Copy Markdown
Owner

Upgrading a background service could discard its working directory and custom options. If the new service started but failed activation checks, it could also remain alive and prevent recovery. Save the effective launch settings privately, preserve the existing token and TLS references, and verify that the restarted service retains the previous endpoint and mode.

Capture the new candidate's process identity independently of health. Before rollback, revalidate its complete private state and process birth identity, stop that owned candidate, then restore and verify the previous executable and runtime. If ownership or state has changed, leave that process untouched, retain the backup, and report the original failure plus incomplete recovery.

Legacy default launches use conservative OS argument and working-directory inspection, including the released launcher's canonical log path. Ambiguous custom legacy settings require manual migration before interruption. Systemd and launchd keep their existing definitions. Canonical upgrade documentation explains that this new updater cannot retroactively change the custom-restart behavior shipped inside v1.9.1.

This builds on #436. The lifecycle change can be reviewed relative to that PR's head, 6ccaac2bdf17697d7d8fa22fd0ec21307ab38c1f; its base remains staging for the required full CI.

Validation at 787a0f31b712246a8acd9edcddead8bca5cf1aec:

  • Focused race checks and strict docs/canonical-document checks passed. Source regressions cover typed flag parsing, unknown fields, path traversal, pinned TLS, prior endpoint/mode, changed process ownership, and joined rollback failures.
  • Five isolated actual-process journeys passed on macOS arm64: custom activation; live-candidate rejection and verified rollback; changed-state refusal without signaling; migration of the actual released v1.9.1 default service; and refusal of an ambiguous v1.9.1 custom launch before interruption. The original aliased-home migration fixture passes after the canonical log-path correction.
  • Those journeys use exact-source command logic with local archive/checksum input and real released/candidate executables. They preserve actual endpoint, mode and authentication, all non-CWD launch fields exactly, the CWD directory identity, and policy/audit/TLS bytes. Owned services, listeners and disposable homes were cleaned up. No provider calls were made.
  • Full required source/security gate passed (go test ./..., go vet ./..., make security-assurance, diff checks). Exact-head Linux, macOS, Windows, package, container, policy, Python and documentation CI passed in CI run 34565216569 and its associated docs check. Independent review found no unresolved material issue in this scoped change.

The first Windows run exposed Unix-only expectations in two tests. The certificate regression now compares with the actual loader's native relative open; the already-current CLI case explicitly exercises a supported self-upgrade branch while existing Windows installer-refusal coverage stays intact. Production behavior was unchanged by that test correction. All local and actual-process checks above were repeated on the updated head.

The process checks are conservative repeated OS observations, not atomic cross-platform process handles. Background-process acceptance does not establish installed systemd/launchd behavior or a public updater journey to an unpublished release. No release or expanded integration support is claimed.

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