Skip to docs content
How to Publish a Plugin
Open Source
Free Cloud
Pro
SDK current
Updated 2026-09-04

How to Publish a Plugin

Editions: Open Source · Free Cloud · Pro

Pipeline from apito-io/plugins CONTRIBUTING, Cloudinary build-release.yml, and plugin-release-sync.yml.

git tag vX.Y.Z
  → build-release.yml
  → GitHub Release zips + checksums
  → repository_dispatch plugin-release
  → apito-io/plugins plugin-release-sync
  → Update registry JSON + sign catalog
  → catalog-v1 release
  → Engine Install / Update
  → Project activate + env

Author steps

  1. Public GitHub repo, Apache-2.0, id hc-<name>-plugin.
  2. Copy Cloudinary build-release.yml: tests, UI build, six OS/arch zips (linux/darwin/windows × amd64/arm64). Each zip has root-level binary + config.yml + ui.js.
  3. Zip name: hc-<name>-plugin-v<semver>-<os>-<arch>.zip. Never latest URLs in the registry.
  4. Tag vX.Y.Z matching config.yml plugin.version and sdk.Init.
  5. First plugin: PR registry/<id>.json to apito-io/plugins. Reviewers check handshake (APITO_PLUGIN / apito_plugin_magic_cookie_v1), capabilities allowlist, SHA-256, byte size. Label official for auto-merge after Registry CI.
  6. Later versions: set REGISTRY_DISPATCH_TOKEN on the plugin repo. The notify-registry job sends repository_dispatch plugin-release so plugin-release-sync updates catalog JSON without a manual PR.
  7. Super-admin: Administrator → Plugins → Install / Update. Engine: catalog signature → SHA-256 zip → zip-slip-safe extract → config.yml vs catalog runtime (version stamp if the zip forgot to bump) → hot-load.
  8. Project admin activates and sets env_vars.

CLI alternative: apito plugin add hc-cloudinary-plugin (still Engine-side verify + install).

Registry JSON

Point releases[] at immutable GitHub Release asset URLs. Include SHA-256 and size. plugin_version / runtime.version must match the zip config.yml after extract.

First-plugin PRs fail if registry/<id>.json is missing. Later dispatch also fails if that file was never merged.

Engine install path

  1. Verify catalog-v1 Ed25519 against Engine PLUGIN_REGISTRY_PUBLIC_KEY (or keys/catalog.pub).
  2. Download the OS/arch zip; check SHA-256.
  3. Extract without zip-slip.
  4. Compare config.yml id, capabilities, handshake to catalog runtime. If those match but version differs, installer stamps catalog version onto the YAML.
  5. Hot-load the HashiCorp child.

Ops gotchas (no secrets)

  • PLUGIN_REGISTRY_SIGNING_KEY on apito-io/plugins must be the private key matching Engine PLUGIN_REGISTRY_PUBLIC_KEY / keys/catalog.pub. Wrong key → live catalog-v1 fails verify → Engine falls back to on-disk .catalog cache. Marketplace then looks “stuck” on an old snapshot.
  • config.yml version must match catalog runtime.version. Stamping is a safety net, not a substitute for bumping YAML + sdk.Init + the git tag.
  • After replacing ui.js locally, Engine must reload so bundle_sha256 reseals. Otherwise Console shows checksum mismatch / “no signed bundle”.

Never commit catalog.priv or signing material.

Checklist

Done Check
Public repo, Apache-2.0, hc-*-plugin
Tag = config version = sdk.Init
Six zips, root-level files, checksums txt
First: registry/<id>.json PR; later: dispatch token
Handshake v1 cookie pair
Capabilities from the allowlist only
Super-admin Install, then project Activate

Back to Architecture or the operator hub Plugins.