Watch
1
0
Fork
You've already forked RedFlag
0
RedFlag/server/internal/services/release_manifest.go
Fimeg ff2f30f47a v0.2.9.3: device classification + ARM support — Pixel 3 lands
DEVICE-002: ARM machine-ID fallback — device-tree model + /etc/machine-id
combo, then /proc/cpuinfo Serial (all-zero rejected), before the weak
hostname fallback. Hardware-bound IDs on DMI-less devices.

DEVICE-001: agent detects device_type (server/desktop/phone/tablet) from
/sys signals — system battery (scope=Device peripherals excluded, UPS
excluded), DRM connector state, framebuffer min-dimension for phone/tablet
split. Reports device_type/device_model/os_distro in registration and
system-info paths.

SERVER-001: migration 061 — device_type, device_type_manual (operator
override, never agent-written), device_model, os_distro on agents.
effective_device_type computed into every serialized agent.

SERVER-002: PUT /admin/agents/:id/device-type — set/clear override,
enum-validated, journaled.

WEB-001: device-type icons + fleet filter, device model in list, detail
header badge with reclassify dropdown, os_distro surfaced.

INSTALL-003: arm64 install path unblocked — helper (required manifest
component) now cross-built aarch64-unknown-linux-musl via rust-lld in the
server image, signed at boot (helperArches += arm64), listed in the release
manifest. Install template already handled uname -m and pacman.

Plus in-flight: desktop tray wiring, enrollment page polish, CI workflow
updates, RAF session-broker/pacman-scanner docs, native installer scaffold.
2026-07-06 18:21:23 -04:00

76 lines
3.8 KiB
Go

package services
// Release manifest — the cold-start trust root and component healthcheck anchor.
//
// Two audiences, one document:
// 1. Install-time: the installer fetches the manifest, verifies the Ed25519
// signature over the verbatim body, then checks every downloaded binary
// against its matching artifacts entry before executing anything.
// 2. Post-install healthcheck: walks Components, runs version_cmd on each
// installed binary, verifies provisioning state, emits a signed checkoff
// report (local journal + server security event).
//
// Signed with the server's instance Ed25519 key (TOFU pubkey on first contact,
// pinned on upgrade). The signed bytes are the verbatim JSON; the signature
// travels in X-Content-Signature, the key fingerprint in X-Key-Id.
//
// CI generates the authoritative manifest at release time (embedded in the
// server binary); at serve time the server re-signs with its instance key.
// A release whose manifest lists a component without a built, version-self-
// reporting artifact fails the release gate — no silent drop-out.
// ManifestArtifact is one released binary's expected identity.
type ManifestArtifact struct {
Platform string `json:"platform"`
Architecture string `json:"architecture"`
Filename string `json:"filename"`
SHA256 string `json:"sha256"`
Size int64 `json:"size"`
}
// ManifestComponent describes one installable/checkable piece of the release.
// Required components block install completion; optional ones are skipped
// gracefully when unavailable.
type ManifestComponent struct {
Name string `json:"name"`
Kind string `json:"kind"` // docker, binary, embedded
Required bool `json:"required"`
VersionCmd string `json:"version_cmd"` // e.g. "--version"
Provisioning []string `json:"provisioning,omitempty"` // healthcheck steps (desktop: autostart_entry, redflag-local_group, desktop_user_membership)
}
// ReleaseManifest is the signed component+artifact catalog for one version.
//
// SupplyChain is the running server's own dependency attestation (built-time
// scan verdict + accepted exceptions + build substrate). It rides the manifest
// signature so the installer can show "safe checks" without a second trust root,
// and refuse on an un-attested or blocked posture.
type ReleaseManifest struct {
Version string `json:"version"`
GeneratedAt int64 `json:"generated_at"`
KeyID string `json:"key_id"`
Components []ManifestComponent `json:"components"`
Artifacts []ManifestArtifact `json:"artifacts"`
SupplyChain SupplyChainPosture `json:"supply_chain"`
}
// ComponentCatalog returns the fixed component set for a release.
// This is the authoritative list — CI's gate job enforces that every component
// here has a built, version-self-reporting artifact.
func ComponentCatalog() []ManifestComponent {
return []ManifestComponent{
{Name: "server", Kind: "binary", Required: true, VersionCmd: "--version"},
{Name: "agent", Kind: "binary", Required: true, VersionCmd: "--version"},
{Name: "helper", Kind: "binary", Required: true, VersionCmd: "--version"},
{Name: "desktop", Kind: "binary", Required: false, VersionCmd: "--version",
Provisioning: []string{"autostart_entry", "redflag-local_group", "desktop_user_membership"}},
{Name: "web", Kind: "embedded", Required: true},
// installer (INSTALL-002): release-gate presence check only, not a
// post-install healthcheck target — it's a delivery mechanism, not a
// running artifact (the thing it installs, "server", is already its
// own entry above). No VersionCmd: an MSI can't self-report a
// version by being executed. Windows-only today (RedFlagSetup.msi),
// so Required: false until macOS/Linux installers exist too.
{Name: "installer", Kind: "binary", Required: false},
}
}