Use scoped services

Project-environment runtime callbacks receive brokered services, not global credentials or host handles. Each service is scoped to the provider, profile, and operation Terminay issued.

Read a profile

call.profiles.get(profileId) returns your provider’s saved non-secret values, a list of secret fields, and a revision. It cannot read another provider’s profiles.

Use a secret or SSH identity

Declare secrets:resolve or ssh-agent:use in the manifest first. Secret bytes exist only inside the withValue callback and are zeroized by the host afterwards. Do not return, cache, log, or put them into a status or error.

TypeScript
async function authenticate(profileId: string, call: ProviderCallContext) {
  const identities = await call.sshAgent.listIdentities({
    profileId,
    purpose: 'ssh-user-authentication',
  });

  const identity = identities[0];
  if (!identity) throw new Error('Choose an SSH identity.');

  const signature = await call.sshAgent.sign({
    profileId,
    purpose: 'ssh-user-authentication',
    identityId: identity.identityId,
    algorithm: identity.algorithm,
    challenge: new TextEncoder().encode('server challenge'),
  });

  return call.secrets.withValue(
    { profileId, fieldId: 'api-token', purpose: 'create-preview' },
    async (token) => requestPreview({
      token: new TextDecoder().decode(token),
      signature,
    }),
  );
}

SSH identity IDs are opaque host-issued handles. You can list permitted public identities and ask the selected identity to sign one bounded SSH authentication challenge; extensions never receive an agent socket or private key.

Call a provider dependency

A dependency is an extension contract, not an npm import. Declare a compatible extension dependency, then call only an operation the target provider declares in its manifest. The host checks both sides before dispatching it.

TypeScript
// Caller: its manifest declares a compatible dependency on acme.ssh.
const result = await call.dependencies.call(
  {
    providerId: 'ssh',
    operation: 'open-managed-environment',
    payload: { host: 'preview.example.com' },
  },
  {
    deadlineAt: call.deadlineAt,
    signal: call.signal,
    idempotencyKey: call.idempotencyKey,
  },
);

// Target: only a manifest-declared operation reaches this handler.
dependencyOperations: {
  async call(request, context) {
    if (request.operation !== 'store-managed-key') {
      throw new Error('Unsupported operation');
    }
    if (!context.idempotencyKey) throw new Error('Missing idempotency key');

    const saved = await context.vault.put({
      bindingKey: 'managed-key',
      purpose: 'SSH authentication',
      value: keyBytes,
      idempotencyKey: context.idempotencyKey,
      expectedRevision: context.expectedRevision,
    });
    return { bindingRef: saved.binding.bindingRef };
  },
}

A target handler receives caller identity, deadline, cancellation, retry metadata, and its own vault only. It does not receive the caller’s profile, secrets, filesystem, or SSH agent. Vault bindings are opaque and scoped to that target provider.

Respect operation boundaries

BrokerAvailable operationBoundary
Profilesget()Your provider’s profile, with secret values omitted.
SecretswithValue()One profile field, one transient callback.
SSH agentlistIdentities(), sign()Authorized identity metadata and a bounded authentication signature.
Dependenciescall()A declared provider and its declared operation.
Target vaultput(), withSecret(), remove()An opaque binding owned by the target provider.

Next steps

Use these brokers inside a project-environment provider. The complete list is in the permissions and brokers reference.