docs(openspec): archive fpagent-install-upgrade and sync specs

Documents release pinning (--tag), the pinned-tag metadata route,
installed-version tracking with upgrade reporting, and restart of a
managed running service on upgrade; syncs the four requirements into the
fpagent-installer main spec.
This commit is contained in:
2026-10-02 11:41:50 +01:00
parent ff62770bcc
commit 35d895574f
6 changed files with 308 additions and 0 deletions
@@ -0,0 +1,64 @@
# Design
## Context
See proposal.md — Why. The `fpagent-installer` capability (change
`fpagent-release-installer`) installs the newest release and hands off to the
bundle's `deploy/install.sh`, which replaces the binary but only warns when a
daemon is running. The bundle name already embeds the git hash
(`fpagent-<hash>-<platform>.tar.gz`) and `bundle.sh` already builds the binary
with that hash as its embedded `Version`.
## Goals / Non-Goals
**Goals:** install a pinned release; make a rerun a real upgrade that reports
what changed and takes effect; keep both install paths (hosted and direct
bundle) consistent.
**Non-Goals:** a separate version service or a new `--version` CLI flag; signing
or provenance beyond sha256; a downgrade-unsafe rollback.
## Decisions
1. **The version is the asset-name git hash.** It is already the binary's
embedded `Version` and needs no new endpoint or flag. The hosted installer
parses it, and also writes it as `VERSION` in the extracted bundle so the
bundle installer has it even for bundles built before this change.
2. **The bundle installer owns the upgrade reporting and the restart.** It
knows `INSTALL_PATH` and the service; the hosted installer only fetches,
verifies and hands off. `bundle.sh` ships `VERSION` so direct bundle installs
behave the same. The stamp lives at `${INSTALL_PATH}.version`, so a custom
`--install-path` keeps its own record, and uninstall removes it.
3. **Restart only on a managed, already-running service.** `enable --now` starts
a stopped unit; for an upgrade the installer checks `is-active` before
enabling and restarts only if it was active, avoiding a redundant restart on
a fresh install.
4. **`--tag` reuses the release handler.** A second same-origin metadata route
(`/fpagent/releases/tags/:tag`) shares the latest route's handler, so the
filtering and non-disclosure rules are identical; the installer switches only
the metadata URL, then downloads by the resolved tag.
## Risks / Trade-offs
- [Bundles built before this change carry no VERSION and do not restart] → the
hosted installer writes VERSION from the asset name (fixes reporting), but the
restart is in the bundle and appears only after a new `fingerprint-agent`
release. Until then upgrades still need a manual restart.
- [Upgrade without `--enable-service` leaves a running daemon on the old binary]
→ the installer warns; the documented install command uses `--enable-service`.
- [A pinned tag whose assets differ] → the tag's own metadata drives asset
selection, the same as latest.
## Migration Plan
Release a new `fingerprint-agent` bundle (ships VERSION and restarts on
upgrade), then deploy the app. The hosted installer is backward compatible: with
an older bundle it reports the version but the bundle's older installer ignores
the stamp. Rollback = revert the app; `--tag` can pin the previous release.
## Open Questions
None.