# `Lightning.Credentials.Resolver`
[🔗](https://github.com/OpenFn/lightning/blob/main/lib/lightning/credentials/resolver.ex#L32)

Provides credential resolution abstraction for workflow execution.

Resolves credentials by matching the project's environment to the credential's
environment body. For OAuth credentials, passes the environment body during
token refresh.

# `error_reason`

```elixir
@type error_reason() ::
  :not_found
  | :environment_not_configured
  | :project_not_found
  | :environment_mismatch
  | Lightning.Credentials.oauth_refresh_error()
  | term()
```

# `keychain_selectors`

```elixir
@type keychain_selectors() :: %{
  required(Ecto.UUID.t()) =&gt;
    {:ok, external_id :: String.t() | nil}
    | {:error, :keychain_input_unavailable | :invalid_keychain_path}
}
```

# `resolve_error`

```elixir
@type resolve_error() :: {error_reason(), Lightning.Credentials.Credential.t() | nil}
```

# `keychain_selectors`

```elixir
@spec keychain_selectors(Lightning.Run.t()) :: keychain_selectors()
```

Reads, for each keychain the run's jobs use, the external id its path selects
from the run's input.

Projects that don't save dataclips have the input wiped as soon as the worker
fetches it, which is before it asks for any credential. Call this before the
wipe and pass the result to `resolve_credential/3`.

# `resolve_credential`

```elixir
@spec resolve_credential(
  Lightning.Credentials.Credential.t(),
  environment :: String.t()
) ::
  {:ok, Lightning.Credentials.ResolvedCredential.t()}
  | {:error, resolve_error()}
@spec resolve_credential(Lightning.Run.t(), credential_id :: String.t()) ::
  {:ok, Lightning.Credentials.ResolvedCredential.t() | nil}
  | {:error, :not_found | resolve_error()}
```

Resolves a credential for a run by matching the project's environment,
or resolves a credential directly for a specific environment.

For a run, keychain credentials are selected from `keychain_selectors` (see
`keychain_selectors/1`). When it is `nil` they are read from the run's
stored input.

# `resolve_credential`

```elixir
@spec resolve_credential(
  Lightning.Run.t(),
  credential_id :: String.t(),
  keychain_selectors() | nil
) ::
  {:ok, Lightning.Credentials.ResolvedCredential.t() | nil}
  | {:error, :not_found | resolve_error()}
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
