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

# alchemy.secret()

> Create encrypted secrets for secure storage in Alchemy state files

# alchemy.secret()

Wraps a sensitive value so it will be encrypted when stored in state files. Requires a password to be set either globally in the alchemy application options or locally in an `alchemy.run()` scope.

## Signature

```typescript theme={null}
function secret<T = string>(
  unencrypted: T | undefined,
  name?: string
): Secret<T>
```

## Parameters

<ParamField path="unencrypted" type="T" required>
  The sensitive value to encrypt in state files. Cannot be `undefined`.
</ParamField>

<ParamField path="name" type="string">
  Optional name for the secret. Used for debugging and logging. If not provided, an auto-generated name will be used.
</ParamField>

## Returns

<ResponseField name="Secret" type="Secret<T>">
  A Secret wrapper that encrypts the value when serialized to state files.

  <ResponseField name="unencrypted" type="T">
    The unwrapped sensitive value. Only accessible in code, never stored in state files.
  </ResponseField>

  <ResponseField name="name" type="string">
    The name of the secret.
  </ResponseField>

  <ResponseField name="type" type="'secret'">
    Type identifier for the Secret wrapper.
  </ResponseField>
</ResponseField>

## Environment Variable Helper

### alchemy.secret.env

A convenient helper for creating secrets from environment variables with better error messages.

```typescript theme={null}
alchemy.secret.env.API_KEY
// Equivalent to: alchemy.secret(alchemy.env("API_KEY"))

alchemy.secret.env("API_KEY")
// Same as above
```

**Advantages over `alchemy.secret(process.env.X)`:**

* Automatically throws if the environment variable is not set
* Provides clear error messages with the variable name
* More concise syntax

## Password Configuration

Secrets require a password for encryption/decryption. The password can be provided in two ways:

### Global Password

Set a password when creating the application scope:

```typescript theme={null}
const app = await alchemy("my-app", {
  password: process.env.SECRET_PASSPHRASE
});

const resource = await Resource("my-resource", {
  apiKey: alchemy.secret(process.env.API_KEY)
});
```

### Scoped Password

Set a password for a specific scope using `alchemy.run()`:

```typescript theme={null}
await alchemy.run("secure-scope", {
  password: process.env.SCOPE_SECRET_PASSPHRASE
}, async () => {
  const resource = await Resource("my-resource", {
    apiKey: alchemy.secret(process.env.API_KEY)
  });
});
```

## Secret Class

The `Secret` class provides static methods for working with secrets:

### Secret.wrap()

Ensures a value is wrapped in a Secret.

```typescript theme={null}
static wrap<T>(value: T | Secret<T>): Secret<T>
```

<ParamField path="value" type="T | Secret<T>" required>
  The value to wrap. If already a Secret, returns it unchanged.
</ParamField>

**Example:**

```typescript theme={null}
const wrapped = Secret.wrap("my-value");
const alreadyWrapped = Secret.wrap(wrapped); // Returns the same Secret
```

### Secret.unwrap()

Unwraps a Secret if it is wrapped, otherwise returns the value.

```typescript theme={null}
static unwrap<T, U = T>(value: T | Secret<U>): T | U
```

<ParamField path="value" type="T | Secret<U>" required>
  The value to unwrap.
</ParamField>

**Example:**

```typescript theme={null}
const secret = alchemy.secret("my-password");
const unwrapped = Secret.unwrap(secret); // "my-password"
const plain = Secret.unwrap("plain-value"); // "plain-value"
```

## Type Guard

### isSecret()

Checks if a value is a Secret wrapper.

```typescript theme={null}
function isSecret<T = string>(value: any): value is Secret<T>
```

<ParamField path="value" type="any" required>
  The value to check.
</ParamField>

**Returns:** `true` if the value is a Secret, `false` otherwise.

**Example:**

```typescript theme={null}
import { isSecret } from "alchemy";

const secret = alchemy.secret("password");
if (isSecret(secret)) {
  console.log(secret.name);
}
```

## Examples

### Basic Usage

```typescript theme={null}
import { alchemy } from "alchemy";

const app = await alchemy("my-app", {
  password: process.env.SECRET_PASSPHRASE
});

// Create a secret from an environment variable
const apiKey = alchemy.secret(process.env.API_KEY);

const worker = await Worker("api", {
  bindings: {
    API_KEY: apiKey
  },
  entrypoint: "./src/worker.ts"
});

await app.finalize();
```

### Using Environment Variable Helper

```typescript theme={null}
import { alchemy } from "alchemy";

const app = await alchemy("my-app", {
  password: process.env.SECRET_PASSPHRASE
});

// Preferred: Better error messages
const apiKey = alchemy.secret.env.API_KEY;
const dbPassword = alchemy.secret.env.DATABASE_PASSWORD;

const database = await Database("db", {
  password: dbPassword
});

const worker = await Worker("api", {
  bindings: {
    API_KEY: apiKey
  },
  entrypoint: "./src/worker.ts"
});

await app.finalize();
```

### Flexible Input Types

```typescript theme={null}
import { alchemy, Secret } from "alchemy";

interface MyResourceProps {
  // Accept either a plain string or a Secret
  password: string | Secret;
}

const MyResource = Resource(
  "my::Resource",
  async function (
    this: Context<MyResource>,
    id: string,
    props: MyResourceProps
  ): Promise<MyResource> {
    // Unwrap the secret for API calls
    const password = Secret.unwrap(props.password);
    
    const result = await api.create({
      password // plain string for API
    });

    // Wrap the secret for storage
    return {
      id,
      password: Secret.wrap(props.password)
    };
  }
);

// Usage: Can pass either a string or Secret
const resource1 = await MyResource("r1", {
  password: "plain-string" // Auto-wrapped
});

const resource2 = await MyResource("r2", {
  password: alchemy.secret("encrypted") // Already wrapped
});
```

### State File Representation

When secrets are stored in state files (`.alchemy/{stage}/{resource}.json`), they are encrypted:

```json theme={null}
{
  "kind": "cloudflare::Worker",
  "id": "api",
  "props": {
    "bindings": {
      "API_KEY": {
        "@secret": "U2FsdGVkX1+K9j3h..." // Encrypted value
      }
    }
  },
  "output": {
    "url": "https://api.example.workers.dev"
  }
}
```

### Scoped Secrets

```typescript theme={null}
import { alchemy } from "alchemy";

const app = await alchemy("my-app");

// Different secrets for different scopes
await alchemy.run("production-api", {
  password: process.env.PROD_SECRET_PASSPHRASE
}, async () => {
  const prodDb = await Database("db", {
    password: alchemy.secret(process.env.PROD_DB_PASSWORD)
  });
});

await alchemy.run("staging-api", {
  password: process.env.STAGING_SECRET_PASSPHRASE
}, async () => {
  const stagingDb = await Database("db", {
    password: alchemy.secret(process.env.STAGING_DB_PASSWORD)
  });
});

await app.finalize();
```

### Error Recovery

If you lose the encryption password, you can use `--erase-secrets` to recover:

```bash theme={null}
# This will treat all secrets as undefined and allow you to redeploy
bun ./alchemy.run.ts --force --erase-secrets
```

## Security Best Practices

1. **Never commit passwords to version control**: Store passwords in environment variables or use a secret management service.

2. **Use different passwords for different stages**:
   ```typescript theme={null}
   const password = process.env[`${stage.toUpperCase()}_SECRET_PASSPHRASE`];
   ```

3. **Rotate passwords periodically**: Update your password and redeploy to re-encrypt all secrets.

4. **Use `alchemy.secret.env` for better error messages**:
   ```typescript theme={null}
   // ✅ Good: Clear error if API_KEY is missing
   const apiKey = alchemy.secret.env.API_KEY;

   // ❌ Less clear: Generic error message
   const apiKey = alchemy.secret(process.env.API_KEY);
   ```

5. **Don't log or print secrets**:
   ```typescript theme={null}
   console.log(secret); // Prints: Secret(API_KEY)
   console.log(secret.unencrypted); // ⚠️ Exposes the secret!
   ```

## Related

* [alchemy()](/api/alchemy) - Create application scope with password
* [alchemy.run()](/api/alchemy#run) - Create scoped password
* [Resource](/api/resource) - Using secrets in resources
