Skip to main content

Two methods

MethodBest for
User-provided secrets (Keychain)Most apps — the user enters secrets at first open; stored in macOS Keychain
Encrypted secrets in packageDistributing apps with pre-configured secrets bundled inside
The manifest declares which secrets the app needs:
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:
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