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

# Credential Isolation

> The caller that proposes an action never holds the credential that executes it. Session credentials are issued fresh, scoped to one call, and consumed once.

<Info>**\[AVAILABLE] as a mechanism, \[PARTIAL] as a system-wide guarantee.** `packages/execution-control`, `packages/connector-sdk`. See the scope note below before treating this as true of every connector.</Info>

## What it is

Credential resolution happens exclusively inside the gateway boundary, after every
[gateway](/concepts/the-gateway) check has passed. The caller that proposed the action, the
Runtime, and the Policy Engine never see the credential a connector uses to actually act.

```typescript theme={null}
// packages/execution-control/src/SessionCredentialVault.ts
interface SessionCredentialVault {
  issue(...): Promise<SessionCredential>;   // single-use, time-bounded lease
  consume(sessionCredentialId: string): Promise<ExecutionCredential>;  // only once
  revoke(sessionCredentialId: string): Promise<void>;
}
```

## Why it exists

If the entity proposing an action, increasingly an AI agent, ever held a live, reusable
credential, every guarantee upstream (deterministic policy, signed authorization, gateway
re-verification) would still leave that credential extractable and reusable outside the
authorized flow. Credential isolation closes that gap structurally: there is no code path
where a proposer receives a credential, because credentials are never routed to it in the
first place.

## How it behaves

```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
`CredentialVault` interface, so `InMemorySecureConnector` resolves credentials through it
exactly as it always has. Two providers ship: `StaticCredentialProvider` (an in-memory map,
hermetic tests and local development only) and `EnvironmentCredentialProvider` (resolves
from `process.env` via a connector-to-variable-name mapping).

A session credential is issued, consumed exactly once, and can be revoked:

```typescript theme={null}
// packages/execution-control/src/SessionCredentialVault.ts:86-110
async consume(sessionCredentialId: string): Promise<ExecutionCredential> {
  const record = /* ... */;
  if (record.revoked) {
    throw new Error(`Session credential has been revoked: ${sessionCredentialId}.`);
  }
  // ...
}
```

### 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, 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. 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 records](/concepts/execution-trust-records).

## Minimal example

```typescript theme={null}
const provider = new EnvironmentCredentialProvider({
  "vendor-payment": "VENDOR_PAYMENT_TOKEN",
});
const vault = new CredentialVaultAdapter(provider);
// InMemorySecureConnector resolves through `vault`, never the raw provider.
```

<Warning>
  **Scope, precisely: this mechanism is real and tested, but in the default server it is only
  ever exercised for one connector.** `packages/api/src/bootstrap/createCredentialProvider.ts`
  wires exactly one mapping, `{ "vendor-payment": "VENDOR_PAYMENT_TOKEN" }`, into one
  `EnvironmentCredentialProvider`, registered against the one connector the server wires up
  (see [The gateway](/concepts/the-gateway)). The isolation guarantee (caller never sees the
  credential, single-use, revocable) is architecturally true for *any* connector routed
  through this seam, and is proven generically by the tests cited above, but making it true
  for a *new* connector today means writing bootstrap code (a new `CredentialProvider` entry,
  a new registry registration), not configuration. There is no dynamic, general-purpose "any
  connector automatically gets isolated credentials" path yet. Treat the isolation guarantee
  as proven for the mechanism and for `vendor-payment` specifically, not as a system-wide
  property of arbitrary connectors you haven't wired yet.
</Warning>

## \[FUTURE]: cloud secret managers

Only the `CredentialProvider` interface seam is defined. No integration exists yet for
HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, or 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.

## Next

<CardGroup cols={2}>
  <Card title="Gateway attestation" icon="stamp" href="/concepts/gateway-attestation">
    The request-bound signature that authenticates the gateway to a connector.
  </Card>

  <Card title="Add a connector with the Connector SDK" icon="plug" href="/integrations/connector-development-guide">
    What wiring a new connector into this seam actually requires.
  </Card>
</CardGroup>
