Skip to Content
Numinance
Architecture

Plugin host

How out-of-process gRPC plugins are launched, handshaken, sandboxed and mediated by the host, with no ambient authority.

View as .mdUpdated
Available in public spec

PluginService and HostService are public contracts. The host that serves them is part of the proprietary runtime and is designed.

Build once against the contract. Bring your own capabilities. The plugin describes what it needs; Numinance decides what it gets.

Invocation sequence

Plugin invocation sequence

In what order do host and provider talk, and who decides what?

Illustrative · simulated
Scenario

Policy allows the action; the provider runs it and every privileged step goes through the host.

HostProviderEgressEvidence

Host: Plugin host + policy decision point · Provider: Plugin subprocess · Egress: Broker / egress proxy · Evidence: Evidence writer (runner identity)

Step 1 of 14

Host launches the subprocess

exec + NUMINANCE_PLUGIN_COOKIE

Message and fields
  • NUMINANCE_PLUGIN_COOKIE = MagicCookie (plugin.CookieEnv)
  • NUMINANCE_PLUGIN_PROTOCOLS (offer)
  • host address env (plugin.HostAddrEnv)
Who holds authority
Host: it starts the process and offers the protocol versions. The host identifies the plugin by the connection it established at launch, never by request content.
✕ The provider can not
The cookie is not a secret and not authority: it only stops a user from running the provider binary by hand. A provider with a wrong cookie refuses to serve.

Allowed. Step 1 of 14: Host launches the subprocess. exec + NUMINANCE_PLUGIN_COOKIE. Host: it starts the process and offers the protocol versions. The host identifies the plugin by the connection it established at launch, never by request content.

▶ selected message◆ host policy decision✕ denied or rejectedName typed RPC from the spec
Text description

Illustrative and simulated: nothing here talks to a running host. RPC and field names are the ones in proto/numinance/plugin/v1 and sdk/go/plugin.

  1. The host starts the provider subprocess with NUMINANCE_PLUGIN_COOKIE set to the magic cookie, then calls Handshake, GetManifest and GetDescriptors on PluginService.
  2. The policy decision and the grant happen on the host, outside the model and before the provider sees the action.
  3. If allowed, the host calls Invoke (server-streaming) with an Envelope whose ActionContext the host sets. The provider may call back on HostService: RequestCredential returns an opaque handle that only works through the egress proxy, which injects the real token; EmitEvidence submits evidence that the host appends under the runner identity; ReportProgress reports progress.
  4. The stream ends with an ActionResult; the host records the outcome, may call Health, and finally Shutdown, which first revokes handles and egress grants.
  5. If policy denies, Invoke is never sent and the denial is recorded as evidence. If the provider requests a credential intent that is not in its declared credential_intents, the host rejects it and records the call.

The provider never holds authority: it cannot approve, widen a grant, see a credential, or append evidence.

Roles

RoleImplementsResponsibility
PluginPluginServicePerforms capability verbs for one or more ports
HostHostServiceMediates every privileged request the plugin makes
Enginen/aDecides when to call a plugin and obtains the policy decision first

PluginService has Handshake, GetManifest, GetDescriptors, Invoke (server streaming), Health and Shutdown. HostService has Log, EmitEvidence, RequestCredential, ResolveReference (server streaming) and ReportProgress.

Handshake and manifest

The host offers its spec version, the protocol versions it will speak, the ports of the installed manifest and the non-core capabilities it knows. The plugin answers with one protocol version from that offer and a subset of capabilities present in both the offer and its manifest. Anything else aborts the handshake. The negotiated version is recorded at install and only that version is offered afterwards, so a plugin cannot later downgrade the protocol.

GetManifest must equal the manifest decoded from the installed package, whose digest the lockfile pins. A mismatch means the host refuses to start the plugin. The manifest is never a source of authority by itself; the host enforces the declared network, filesystem and credential intents.

Sandbox boundaries

  • Each plugin is a separate process in its own container, never co-located with the executor.
  • Egress is limited to the destinations in its manifest, through the egress proxy.
  • The host identifies the calling plugin by the connection it launched, not by request content, and rejects an invocation_id that is not in flight for that plugin.
  • RequestCredential returns an opaque handle bound to the invocation and intent, usable only through the proxy, expiring no later than the invocation deadline. It never returns credential material.
  • Every dispatch carries a host-set ActionContext with a policy_decision_id. The host never dispatches without one.
  • A plugin that cannot accept an idempotency key declares it, and steps calling it need a compensation or approval.

Governed install

Install verifies signature and provenance, computes a permission difference against the lockfile, runs the conformance suite in a sandbox, evaluates policy (widening always needs approval) and pins digest and signer identity. Versions are locked for the duration of a change; nothing is installed dynamically during a run.

Boundary table

PartyHoldsDoes not hold
PluginIts own logic and a handle for the current invocationCredentials, the right to widen its manifest
HostEnforcement and the evidence emit pathThe plugin's business logic
Broker and proxyCredential material and injectionDecisions

Failure cases

  • Handshake offers a lower protocol than locked: aborted.
  • Manifest differs from the pinned package: plugin not started.
  • Call without a policy decision: not dispatched.
  • Request to an undeclared host: denied by the proxy and recorded.
  • Provider unhealthy: Health fails and capability invocations are denied until recovery.

On this page