First slice of the `banger update` package. No CLI yet — this just
defines the wire shape and parsers the rest of the flow will plug
into.
* internal/updater/manifest.go — Manifest / Release types,
ManifestSchemaVersion = 1, the hardcoded URL
https://releases.thaloco.com/banger/manifest.json (var instead
of const so tests can point at httptest), and FetchManifest /
ParseManifest / Manifest.LookupRelease / Manifest.Latest.
The manifest only references URLs (tarball, SHA256SUMS, optional
signature); actual binary hashes come from SHA256SUMS itself,
so manifest tampering can't substitute a hash for a known-good
tarball.
SchemaVersion gates forward-compat: a CLI that doesn't know its
server's schema_version refuses to update rather than guessing.
* internal/updater/sha256sums.go — ParseSHA256Sums tolerates both
GNU `<digest> <file>` (with optional `*` binary prefix) and
BSD `SHA256 (file) = <digest>` formats. Comments and blank
lines are skipped; malformed lines that LOOK like entries are
rejected (silent skipping is the wrong failure mode for a
security-relevant input). Digests are lowercased so the caller
can `==`-compare without worrying about case.
Caps: 1 MiB on the manifest body, 16 KiB on SHA256SUMS, 256 MiB on
release tarballs. Generous-but-bounded; bumping requires a code
change so a server-side mistake can't fill the disk.
Tests: ParseManifest happy path, schema-version-too-new rejection,
five malformed-input cases. ParseSHA256Sums covers GNU + BSD +
star-prefix + comments-and-blanks, six malformed-input rejections,
case-insensitive digest normalisation. FetchManifest end-to-end via
httptest.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>