Scoped brokers

Project-environment callbacks receive broker objects in ProviderCallContext. Every call is checked against the extension, provider, profile, operation, deadline, and cancellation scope that Terminay issued.

Provider call context

MemberMeaning
deadlineAtHost-assigned absolute ISO-8601 deadline. Stop work before it expires.
signalCancellation signal with aborted and throwIfAborted().
idempotencyKey?Stable retry key for retryable mutations.
expectedRevision?Optimistic-concurrency revision for an existing state mutation.
profiles, secrets, sshAgent, dependenciesScoped broker surfaces described below.

Profiles and secrets

TypeScript
async function verifyProfile(context, profileId) {
  const profile = await context.profiles.get(profileId);

  return context.secrets.withValue(
    { profileId, fieldId: 'token', purpose: 'verify API access' },
    async (token) => {
      // Use token only here. Do not log, return, or store it.
      return verifyWithService(profile.values.endpoint, token);
    },
  );
}
BrokerMethod and result
profilesget(profileId) returns an owned provider profile: ID, provider ID, non-secret values, declared secret field IDs, and revision.
secretswithValue({ profileId, fieldId, purpose }, use) passes an owned secret as Uint8Array only to use.

Secret bytes are transient and zeroized after the callback. Do not retain, return, log, serialize, display, or put them in provider state. A secret broker cannot enumerate the vault or resolve another extension’s binding.

SSH agent

MethodInput and result
listIdentities(scope){ profileId, purpose: 'ssh-user-authentication' } → bounded public identity metadata: opaque ID, algorithm, public key, fingerprint, and optional comment.
sign(request)The same scope plus identity ID, algorithm, and bounded authentication challenge → algorithm and signature bytes.

Identity IDs are opaque; the API does not reveal a keychain, agent socket, private-key path, or private key. Both methods require ssh-agent:use.

Provider dependencies

TypeScript
const result = await context.dependencies.call(
  { providerId: 'ssh', operation: 'open-environment', payload: { host: 'prod' } },
  { deadlineAt: context.deadlineAt, signal: context.signal },
);

Declare a compatible extension in extensionDependencies, add the provider:depend permission, and call only a target provider’s manifest-declared operation. A request contains providerId, operation, and JSON payload; the result is JSON.

The target handler receives host-authenticated caller identity, the request’s operation and payload, deadline/cancellation/idempotency/revision fields, and only a target-owned vault. It never receives the caller’s profiles, secrets, SSH agent, or filesystem scope.

Target-owned dependency vault

MethodMeaning
vault.put()Atomically create or replace a target-owned binding from binding key, purpose, bytes, idempotency key, and optional expected revision. Returns an opaque binding and revision.
vault.withSecret()Supply an opaque binding and purpose; secret bytes exist only inside its callback and are zeroized afterward.
vault.remove()Delete a binding with an idempotency key and optional expected revision. Returns deleted or pending.

A binding is durable but opaque and scoped to the extension installation and target provider. It is not a vault path or global secret ID.

Security boundary

Brokers are host-mediated, typed IPC—not direct server internals. They enforce ownership, declared dependencies, operation allowlists, cancellation, and bounded data transfer for each request.