HTTP app repositories
An http(s) repo is a static site serving an index manifest plus one
.app archive (tar.gz of the app package directory) per app — the
SHC equivalent of a helm chart repository. Any web host works: GitLab
Pages, S3, nginx. The shc repo’s own CI publishes the full apps/
catalog this way on every default-branch push and release tag
(apps:index job → GitLab Pages, next to the terraform provider
mirror).
Consuming
Section titled “Consuming”shc repo add shc https://<pages-domain>/apps/index.yamlshc repo sync shcshc install shc/planePrivate hosts work too: shc repo add … --token <t> sends
Authorization: Bearer <t> on both the index fetch and every archive
download (terraform: the shc_repo resource’s token attribute).
Sync parses the index and replaces the repo’s catalog rows; each row’s
source is the resolved archive URL with the digest pinned as a
#sha256=<hex> fragment. On install, the daemon downloads the archive
node-locally, verifies the digest (mismatch fails closed with
X500902REPMAT), and extracts it into the repo’s cache dir — so unlike
git+file:// repos, http repos install from any node.
Index format
Section titled “Index format”index.yaml (JSON also parses — YAML is a superset):
api_version: v1apps: - name: plane version: "1.0.0" description: Project management category: productivity tags: [projects] archive: plane-1.0.0.app # relative to the index URL, or absolute digest: sha256:<hex> # over the archive bytesEntries missing name or archive fail the sync loudly. parent_app /
vapp / homepage / icon carry through to the catalog like the git
crawl does.
Publishing
Section titled “Publishing”go run scripts/build-apps-archives.go -apps <tree> -out <dir> packages
one app per subdirectory (app.yaml required) into byte-reproducible
archives — sorted walk, zeroed times, fixed ownership — so digests only
change when package content changes. It writes <name>.app plus a
<name>.meta.json metadata slice per app; build index.yaml entries
from the meta slices (the shc catalog’s own publisher does exactly that
via scripts/publish-apps-registry.sh +
scripts/gen-apps-registry-index.go). Serve the archives and the index
anywhere; register the index.yaml URL.
Versions are immutable. Consumers pin digests at sync time; never
republish different bytes under the same archive name — bump the app’s
version instead (the archive name embeds it).
Archive rules
Section titled “Archive rules”An archive is the app package dir’s contents at the tar root
(app.yaml, compose.yaml, …). Extraction rejects path traversal,
absolute names, and link entries.