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

# Secrets

> How Vibe handles sensitive values — Keychain storage, encrypted packages, and runtime injection.

## Two methods

| Method                               | Best for                                                                    |
| ------------------------------------ | --------------------------------------------------------------------------- |
| **User-provided secrets (Keychain)** | Most apps — the user enters secrets at first open; stored in macOS Keychain |
| **Encrypted secrets in package**     | Distributing apps with pre-configured secrets bundled inside                |

## Method A: User-provided secrets (recommended default)

The manifest declares which secrets the app needs:

```yaml theme={null}
secrets:
  - name: OPENAI_API_KEY
    required: true
  - name: AWS_SECRET_ACCESS_KEY
    required: false
```

**Flow:**

1. On first open, the host app detects missing required secrets
2. The user is prompted to enter each secret value
3. Secrets are stored in the **macOS Keychain**, scoped to the project instance
4. At service start, secrets are injected as environment variables

**Properties:**

* Secrets never exist inside the package
* Secrets persist across app restarts
* Secrets are scoped per project instance — not shared between instances of the same app
* Deleting a project instance removes its Keychain entries
* Required secrets that are missing prevent the app from starting

## Method B: Encrypted secrets in package

For distribution models where developers ship pre-configured secrets.

The package contains an encrypted blob (`secrets.encrypted`) with the secret values. On open, the user is prompted for a decryption password. The decrypted secrets are held in memory only — never written back to disk.

**Brute-force protection:**

* Exponential backoff after failed decryption attempts
* 5-minute temporary lock after 5 consecutive failures
* Attempt counter resets on success

## Runtime injection

Regardless of storage method, secrets reach services as environment variables. The secret name becomes the environment variable name:

```yaml theme={null}
secrets:
  - name: OPENAI_API_KEY
    required: true
```

→ `OPENAI_API_KEY=<value>` is set in all service environments at start time.

## Safety guarantees

* Secrets never appear in logs (the log collector redacts known secret names)
* Secrets never appear in snapshots (excluded from state copy)
* Secrets are not stored in the immutable package in plaintext
* Keychain-backed secrets survive app restarts
* Secrets are isolated per project instance and never leak between apps
