librelad e601ec8434 feat(distribution): Phase 5 — make_hotfix.sh publisher tooling
The maintainer-side tool that turns a small hotfix SPEC into the two signed
artifacts the install verifies + applies (completes the hotfix product):
  dist/<channel>/payloads/<id>.json(.minisig)   the bounded declarative op list
  dist/<channel>/index.json(.minisig)           the catalog (entry upserted, serial++)
laid out exactly like get.libreportal.org serves it (local-serve testable).

- Reads a spec (envelope fields + an embedded ops array); inlines any
  op `content_file` to content_b64 for convenience.
- Validates id charset + every op name against the applier's CLOSED vocabulary,
  so a typo can't ship an artifact that fails-closed on every box.
- Builds the payload (sha256), the envelope (payload ref {kind,url,sha256,sig}),
  and upserts it into index.json — bumping index_serial, refreshing valid_until
  (LP_HOTFIX_VALID_DAYS, default 30), and recording the publisher in the
  publishers map with role + the footprint public key.
- minisign-signs the payload + index when LP_MINISIGN_SECKEY is set (the offline
  key, kept on the release machine, same as make_release.sh); unsigned otherwise
  for local testing — `libreportal artifact apply` refuses to apply unsigned.

Verified end-to-end (unsigned mode): produces a valid index.json + payload.json
matching the §8.1 envelope that lpFetchIndex / artifactApply consume.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-31 21:22:05 +01:00
..