updater

package
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 7, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package updater checks GitHub Releases for a newer Extension Guard build, downloads and integrity-checks the binaries, and swaps them into place.

The swap is deliberately cooperative. Because the guard runs as a self-healing service (watchdog + SCM recovery), the live binaries cannot simply be overwritten - the service holds guard.exe open and the watchdog fights any restart. Windows won't overwrite or delete a running .exe, but it *will* let you rename one (even the caller's own image), so SwapFiles moves each old binary aside and drops the new one in its place; the caller (cmd/guard's "update" command) pauses the watchdog via the "updating" sentinel, stops the service, swaps, then restarts so the new image loads. See guardsvc for the watchdog stand-down.

Integrity today rests on a SHA-256 manifest served over HTTPS from the release. That catches corruption and casual tampering, but it is NOT a substitute for Authenticode code signing: a compromised release could publish a matching hash. Signing is a hard prerequisite before enabling silent auto-apply in the wild (see docs/pc-version.md) - which is why the service defaults to "notify" rather than "apply".

Index

Constants

This section is empty.

Variables

View Source
var (
	Repo = "codepurse/extension-guard"
)

Repo is the GitHub "owner/name" the updater queries; apiBase is the API root. Both are vars so tests can point them at a local server.

Functions

func CleanupOld

func CleanupOld(dir string)

CleanupOld removes leftover "<name>.old" binaries in dir.

func Compare

func Compare(a, b string) int

Compare returns -1, 0, or 1 as a is less than, equal to, or greater than b, comparing dotted numeric versions ("1.10.0" > "1.9.0"). A leading "v" and any pre-release/build suffix ("-rc1", "+meta") are ignored. The sentinel "dev" (an un-stamped local build) parses to 0.0.0, so a dev build sorts below every real release.

func SwapFiles

func SwapFiles(dir string, staged map[string]string) error

SwapFiles replaces each live binary in dir with its staged "<name>.new" counterpart (staged maps asset name -> staged path, as returned by Release.Stage).

On Unix a running binary can be replaced by rename - the open image keeps executing from the now-unlinked inode - so this is a straight atomic rename with the same move-aside-and-rollback safety net as the Windows path. The ".old" files are removed immediately, since Unix has no objection to unlinking a busy binary.

Types

type Asset

type Asset struct {
	Name   string
	URL    string
	SHA256 string
}

Asset is one downloadable release file resolved to its URL and expected hash.

type FileHash

type FileHash struct {
	Name   string `json:"name"`
	SHA256 string `json:"sha256"`
}

FileHash pins one release binary to its expected SHA-256 (lower-case hex).

type Manifest

type Manifest struct {
	Version string     `json:"version"`
	Notes   string     `json:"notes"`
	Files   []FileHash `json:"files"`
}

Manifest is the manifest.json asset attached to each release. Version mirrors the release tag without a leading "v"; Files lists the SHA-256 of every binary the updater may download.

type Release

type Release struct {
	Version string
	Notes   string
	Assets  []Asset
}

Release is the resolved "latest release" the updater acts on.

func CheckLatest

func CheckLatest(ctx context.Context) (Release, error)

CheckLatest fetches the latest published release and resolves its binaries and expected hashes from the attached manifest.json. It does NOT download the binaries - callers decide whether the version warrants that.

func (Release) Asset

func (r Release) Asset(name string) (Asset, bool)

Asset returns the named asset, or ok=false if the release doesn't carry it.

func (Release) Newer

func (r Release) Newer(current string) bool

Newer reports whether this release is strictly newer than the running build.

func (Release) Stage

func (r Release) Stage(ctx context.Context, dir string, names ...string) (map[string]string, error)

Stage downloads the named assets into dir as "<name>.new", verifying each against its manifest SHA-256. It returns the staged paths keyed by asset name. On any failure it removes whatever it staged, so a partial download is never left behind. dir should be the install directory so the later rename-in-place swap stays on one volume (a cross-volume rename would fail).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL