Skip to main content
[AVAILABLE] as a library. packages/connector-sdk/src/CredentialProvider.ts, CredentialVaultAdapter.ts. Extends execution-control’s CredentialVault — does not replace it.

The seam

export interface CredentialProvider {
  readonly providerId: string;
  resolve(connectorId: string): Promise<CredentialHandle>;
}
A CredentialHandle is opaque, resolved material — { providerId, credentialId, value }. CredentialVaultAdapter adapts any CredentialProvider into execution-control’s existing CredentialVault interface, so the unchanged InMemorySecureConnector resolves credentials through it exactly as it always has. Two providers ship:
  • StaticCredentialProvider — an in-memory map. Hermetic tests and local development only.
  • EnvironmentCredentialProvider — resolves from process.env via a connector-to-variable-name mapping.

What “never leaks” means, precisely

A CredentialHandle’s value necessarily carries the resolved secret — a connector (e.g. HttpConnector) needs it to set an Authorization header. What must never happen is the secret reaching anywhere durable or observable outside that one ephemeral use:
  • Never in ConnectorEvidence. buildConnectorEvidence only ever reads ConnectorRequest/ConnectorResponse fields (business parameters, response metadata) — never ConnectorExecutionContext.credential. redactSensitiveKeys additionally strips any response-metadata key that looks credential-shaped, as defense in depth against a connector author’s mistake.
  • Never in a thrown error. Both providers’ failure messages name only identifiers (connectorId, environment variable name) — never a resolved value. Tested in packages/connector-sdk/tests/unit/credential-provider.test.ts.
  • Never as a raw value reaching a Connector. Every CredentialHandle is branded at creation (brandCredentialHandle); SdkConnectorExecutor rejects any credential that isn’t a branded handle — closing the gap where something upstream of the provider seam hands a Connector a raw secret directly. Tested end-to-end in gateway-integration.test.ts (“rejects a raw (non-provider-resolved) credential”).
  • Never in the Execution Trust Record. Only ConnectorEvidence (never the handle itself) is placed on ExecutionResult.metadata.connector — see Execution Trust Record.

Resolution happens only inside the Gateway

The AI that proposed the work, the Runtime, and the Policy Engine never see a CredentialHandle — it is constructed by CredentialVaultAdapter.getCredential(), called only from inside InMemorySecureConnector.execute(), itself only reachable through ExecutionControlService, itself only reachable through the Execution Gateway after every verification check has passed.

[FUTURE]: cloud secret managers

Only the CredentialProvider interface seam is defined. No integration exists yet for:
  • HashiCorp Vault
  • AWS Secrets Manager
  • Azure Key Vault
  • Google Secret Manager
Any of these would implement CredentialProvider exactly like EnvironmentCredentialProvider does — no cloud SDK dependency has been added to this package, and none is implemented in this milestone.