> ## Documentation Index
> Fetch the complete documentation index at: https://docs.manthan.systems/llms.txt
> Use this file to discover all available pages before exploring further.

# Credential Architecture

> Credential resolution happens exclusively inside the Execution Gateway. A Connector — and the AI that proposed the work — never sees it.

<Info>**\[AVAILABLE] as a library.** `packages/connector-sdk/src/CredentialProvider.ts`,
`CredentialVaultAdapter.ts`. Extends `execution-control`'s `CredentialVault` — does not
replace it.</Info>

## The seam

```typescript theme={null}
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](/trust-record/overview).

## 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.
