Problem
iohr (RFC 0019) is one binary with a closed set of commands. It talks to the API and
the sign-in host and nothing else: no update check, no telemetry, no plugins. That rule
was right for a first release and it is written into the command line's security
requirements.
It now stands in the way. The agent that runs checks and faults inside a company's network (RFC 0029) is a second program with its own release cycle. An engineer who looks after a platform should not have to find it, download it, check its signature by hand, write its configuration from a blank page and wire a credential into it. That is the afternoon of configuration work the agent exists to remove.
The common answers each miss something an enterprise needs:
- A plugin directory on the path (
git-foo, ): any program named right becomes a command. Simple, and nothing checks what the program is. - Install from any repository (
gh extension install owner/repo): convenient, and the trust decision is the person's alone, made once, with no record a security team can review. - Self-updating tools: the vendor decides when code changes on the machine. Banks and regulated companies do not allow it.
Proposal
An extension is a separate program that iohr installs, verifies, pins and runs.
iohr ext install agent fetches it; afterwards iohr agent … hands the rest of the
command line to it. It runs as its own process with its own memory, so a fault in an
extension cannot read the command line's secrets.
Shipped as signed OCI artifacts
Every extension release is an artifact in an OCI registry, the same format container images and charts use, as the OCI 1.1 specifications allow (image spec). One artifact per target platform, with these attached to it:
- a signature made without a long-lived key, by our release workflow's identity (Sigstore cosign);
- build provenance at SLSA build level 3 (SLSA);
- an SBOM (CycloneDX) and a statement of which known vulnerabilities affect it (OpenVEX).
The reason is the customer, not us. A company already runs a registry mirror (Artifactory, Harbor, a cloud registry), already scans what enters it and already enforces signatures on what runs. An OCI artifact fits all of that without a new tool, and works in a network that cannot reach the internet.
Installed, verified, pinned
iohr ext install <name>[@version]resolves the artifact from our registry, or from the registry a company sets once (iohr config set ext.registry …), so every install in that company comes from its mirror.- Before anything runs,
iohrchecks the signature against the identity of our release workflow, the provenance against the source repository, and the digest. A failure stops the install; there is no flag to skip it. - What is installed is written to a lock file: name, version, digest, signer. A team
commits it;
iohr ext syncinstalls exactly that on another machine or in a pipeline. iohr ext list|upgrade|remove|verifydo what they say.upgradeonly happens when a person runs it; nothing updates by itself.
A diagram is drawn here in the RFCs product; this page does not show diagrams yet.
Credentials never leave iohr
An extension never reads the keychain and never sees a refresh token. When it needs to
call the platform it asks iohr over a private channel for an access token, and iohr
returns a short-lived token narrowed to the scopes the extension declares in its
manifest (RFC 0016). The manifest lists those scopes; installing shows them, the way a
phone shows an app's permissions.
A diagram is drawn here in the RFCs product; this page does not show diagrams yet.
What changes in the command line's rules
The rule that iohr talks only to the API and the sign-in host gains one exception: the
extension registry, contacted only by ext install, ext upgrade and ext sync, never
on any other command and never to check for updates. There is still no telemetry. The
change is recorded as a new decision in the command line's own repository, replacing the
one it changes.
Who may publish
At first only InOrbit, signed by our release workflow. Extensions from others are a later decision, once this trust model has been used in anger; when they come they will be named by their signer, never installable without a visible choice.
Alternatives considered
Ship the agent as a separate download only. Possible, and the server form of the agent is exactly that (RFC 0029). On a laptop or in a pipeline it means one more tool to find, verify and keep in step with the command line by hand.
iohr-<name> programs found on the path. The simplest extension model, and the one
with no answer to "what is this program and who built it".
Plugins loaded into the iohr process. Faster to call, and a crash or a flaw in a
plugin becomes the command line's. A separate process costs little and keeps secrets
apart.
WebAssembly components for every extension. A sandbox with nothing granted by default is the right shape for small extensions written by others, and we expect to use it for them. The agent itself proxies traffic and holds long connections, which needs a native program.
Decision
Open. Proposed: extensions as separate programs shipped as signed OCI artifacts, verified before they run, pinned in a lock file, installable from a company's own mirror, handed narrow short-lived tokens, and published only by InOrbit at first.
Publication
The command line's reference gains iohr ext, the developer docs a page on installing
from a mirror and verifying by hand, and the command line's repository a new decision
record for the registry exception.
Status log
- 2026-10-03: opened, with RFC 0029 (the agent), 0030 (domains) and 0031 (reliability in the console).
- 2026-10-03: built in the command line's repository (inorbithr/sdk#40, not yet merged):
iohr ext install|list|upgrade|remove|verify|sync,iohr <name>to run one, and a decision record for the registry exception. Install checks every digest, then a signature and SLSA provenance from our release workflow, offline against the Sigstore root built intoiohr; a company may add keys for a mirror that re-signs. Installs are pinned iniohr-ext.lock. A running extension asks for tokens over a private socket, only for its declared scopes; until the sign-in service can narrow a token, it gets the profile's own short-lived token when that holds every scope asked for. - 2026-10-06: RFC 0073 builds the marketplace on this model: a catalogue, publishers other than InOrbit with their own signing identities, more kinds than programs, review, revocation and paid listings. The rules above stay for every program extension.
- 2026-10-07: Checked:
iohr extmerged in inorbithr/sdk#40 on 2026-10-03. Not verified: whichiohrrelease carries it, or that any extension is published. The catalogue is RFC 0073 (#492, open). Open.