docs(openspec): archive fpagent-release-installer and sync specs
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
# Design
|
||||
|
||||
## Context
|
||||
|
||||
See proposal.md — Why. The `fingerprint-agent` repository and its releases are
|
||||
private: an unauthenticated request to the forge's releases API answers `404`.
|
||||
Releases already publish, per build, a generic bundle
|
||||
(`fpagent-<version>-linux-x86_64.tar.gz`), per-Ubuntu offline bundles
|
||||
(`fpagent-<version>-ubuntu-<codename>-x86_64.tar.gz`) with the libfprint `.deb`
|
||||
closure vendored, and a `.sha256` beside each. Every bundle already contains
|
||||
the fpagent binary, the udev rule, and its own `install.sh` that handles
|
||||
libfprint, udev, `plugdev` and the systemd service. The tools app is an Express
|
||||
server with a hardcoded-configuration policy whose only sanctioned environment
|
||||
variables were the Image Cropper credentials.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- A field laptop installs or updates fpagent with one public command.
|
||||
- The forge credential never reaches the field laptop.
|
||||
- Reuse the bundle's installer rather than reimplementing hardware setup.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- Replacing the bundle installer, or the forge's own release tooling.
|
||||
- Authenticating the installer: it is intentionally public.
|
||||
- Supporting architectures other than x86_64 (the bundle installer already
|
||||
requires it).
|
||||
|
||||
## Decisions
|
||||
|
||||
1. **Proxy the release through the app; do not embed the key in the script.**
|
||||
The credential lives in `GITEA_RELEASE_INSTALL_KEY` and the app fetches the
|
||||
private release server-side. The alternative — rendering the key into the
|
||||
served script so the client could call the forge directly — publishes a
|
||||
repository credential to every installer and any `curl`; rejected.
|
||||
|
||||
2. **Two thin routes, no proxy framework.** `/fpagent/releases/latest` returns
|
||||
a trimmed `{tag, assets:[{name,url}]}` with same-origin URLs, and
|
||||
`/fpagent/releases/download/:tag/:name` streams one asset. Both are
|
||||
registered before the session middleware so they stay public and do no
|
||||
per-request PocketBase work. A single combined "give me the right tarball"
|
||||
route was considered but needs the server to guess the client's OS; the
|
||||
client knows its own codename, so selection happens in the script.
|
||||
|
||||
3. **The installer delegates to the bundle's own `install.sh`.** All hardware
|
||||
and dependency logic already exists and is versioned with the binary;
|
||||
reimplementing it in the hosted script would duplicate it and drift. The
|
||||
hosted script only fetches, verifies, extracts, and forwards flags.
|
||||
|
||||
4. **Bundle selection prefers the codename offline bundle.** When the host's
|
||||
`/etc/os-release` `VERSION_CODENAME` matches a published offline bundle, use
|
||||
it (no network needed for the dependency closure); otherwise fall back to
|
||||
the generic online bundle, whose installer apt-gets libfprint.
|
||||
|
||||
5. **Checksum verification, not signature verification.** The release publishes
|
||||
sha256 only, so the installer verifies sha256 over TLS from the same origin
|
||||
it trusts for the script itself. GPG would require release signing that does
|
||||
not exist yet; deferred.
|
||||
|
||||
6. **Asset names are validated server-side** against a conservative pattern,
|
||||
so a crafted tag or name cannot walk the forge path or reach another host.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [A compromised tools app serves a malicious installer] → the app is already
|
||||
trusted to serve the tools pages and holds the operator session; the
|
||||
installer is not a new trust boundary. TLS to `tools.yrka.app` is the same
|
||||
trust as the app.
|
||||
- [The forge changes its bundle naming] → selection falls back to the generic
|
||||
bundle, and a release with no matching asset fails loudly rather than
|
||||
installing something wrong.
|
||||
- [The app buffers an asset in memory] → bundles are tens of MB; acceptable,
|
||||
and requests are rare. Streaming can replace it if that changes.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
Add `GITEA_RELEASE_INSTALL_KEY` to `.env`/`.env.production` (already supplied)
|
||||
and deploy the app; the installer and proxy are new routes and change no
|
||||
existing behavior. Rollback = remove the routes; nothing else depends on them.
|
||||
|
||||
## Open Questions
|
||||
|
||||
None.
|
||||
Reference in New Issue
Block a user