Developer tools
Extensions
Programs that iohr installs from an OCI registry, verifies, pins and runs, without handing them your long-lived credentials.
An extension is a separate program with its own release cycle that iohr installs, verifies,
pins and runs. The first one is the agent. The design is
RFC 0028; the decision in the SDK
repository is ADR 0012.
iohr ext install agent # the newest release; or [email protected]
iohr ext list # what is installed, with its digest and signer
iohr agent status # iohr <name> … runs the installed program| Command | What it does |
|---|---|
iohr ext install NAME[@VERSION] [--lock FILE] | Fetch, verify and install one (NAME@sha256:DIGEST pins a digest); --lock also pins it in a lock file |
iohr ext list | The installed extensions, their digests and who signed them |
iohr ext upgrade [NAME] [--lock FILE] | Install the newest release of one, or of every installed one; nothing updates by itself |
iohr ext remove NAME [--lock FILE] | Remove one from this machine (and from the lock file) |
iohr ext verify [NAME] | Check again offline: the program's hash, the bundles kept at install, the pinned signer |
iohr ext sync [--lock FILE] | Install exactly what a lock file pins, by digest and signer (default iohr-ext.lock) |
What install checks
Nothing is written to disk until every check passes, and no flag skips them:
- The index and this platform's manifest match their SHA-256 digests (and the digest in the
lock, for
iohr ext sync). - A signature and SLSA v1 build provenance, both Sigstore bundles attached to the artifact,
both from InOrbit's
release.ymlworkflow at a tag, checked offline against the Sigstore trusted root built intoiohr. - The manifest: the name and version asked for, an entrypoint that stays inside the
extension, scopes written as
resource:action. - The layer matches its digest and size; only the entrypoint is taken from it.
Install prints who signed it and the API scopes it may ask for. Every run re-hashes the program first.
Pinning
What is installed is pinned in iohr-ext.lock. To pin a project's extensions in its
repository and install the same digests on another machine or in CI:
iohr ext install agent --lock iohr-ext.lock
git add iohr-ext.lock
iohr ext sync # elsewhere: reads ./iohr-ext.lockCredentials
A running extension never sees your refresh token or the credential store. It asks iohr
for an access token over a private socket (IOHR_EXT_TOKEN_SOCKET, mode 0600), only for
scopes its manifest declares; IOHR_EXT_API is the API's address. Until the platform can
mint narrower tokens, the token handed out is the profile's own 15-minute access token, and
only when it holds every scope asked for.
From a company's mirror
Extensions are OCI artifacts at ghcr.io/inorbithr/iohr-ext/<name>:<version>, one manifest per
platform (Linux, macOS and Windows on x86-64 and arm64). A mirror that copies them with their
referrers (oras cp -r) needs nothing else; point every machine at it once:
iohr config set ext.registry registry.example.com/inorbit/iohr-extA mirror that re-signs what it admits adds its public key, and its signature then passes too:
iohr config set ext.trusted_keys mirror.pub
iohr config get ext.trusted_keys # prints their fingerprintsA mirror that needs a login reads IOHR_EXT_REGISTRY_AUTH=user:password from the environment;
it is never a flag.
Checking by hand
With crane, cosign 3 and the GitHub CLI:
ref=ghcr.io/inorbithr/iohr-ext/agent
digest=$(crane digest "$ref:0.1.0-alpha.7") # compare with the digest in iohr-ext.lock
cosign verify "$ref@$digest" \
--certificate-identity-regexp '^https://github\.com/inorbithr/[^/]+/\.github/workflows/release\.yml@refs/tags/' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
gh attestation verify "oci://$ref@$digest" --owner inorbithr \
--predicate-type https://slsa.dev/provenance/v1What is not checked: whether the release workflow's code is what you expect (the provenance names the repository, workflow and tag for you to read), and revocation (Sigstore has none; a compromised release is answered with a new release and an advisory). The SDK repository's verifying extensions has the full rules.