2 Commits

Author SHA1 Message Date
librelad
8351863719 feat(release): make_app.sh — publish app definition bundles to the artifact index
The marketplace publisher tool: packs containers/<slug>/ (the drop-in app
contract, unchanged) into a deterministic tarball (commit-clamped mtimes +
gzip -n; unchanged apps repack byte-identical and keep their published
version), signs it, copies a sha256-pinned catalog icon, and upserts a
type:"app" / payload.kind:"bundle" envelope into the same team-signed
index hotfixes ride. Catalog metadata (title/category/descriptions) is
parsed line-wise from the app's own .config — one source of truth with the
App Center generators. auto:false is hard-forced: apps never auto-apply.

The index-upsert/serial/freshness/publishers-map and signing logic is
factored out of make_hotfix.sh into lib/release_index.sh, shared by both
tools (make_hotfix.sh behavior preserved; regression-tested alongside an
app entry: serial bump, both payload kinds coexist, valid_until refreshed).
LP_INDEX_VALID_DAYS is the shared freshness knob (LP_HOTFIX_VALID_DAYS
kept as a legacy alias).

Verified: speedtest publish → deterministic repack (identical sha256) →
served via local http.server → real lpFetchIndex/accessors harness 10/10.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-07-03 20:45:02 +01:00
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