Skip to main content
Two databases. Unlock posture decides who can read what.
Per-secret automated reads have moved to the runtime manager. A headless flow cannot answer the elevate-access GUI prompt, so the day-to-day machine path runs through OpenBao (T2), where an agent authenticates via AppRole with zero interactive prompts. The AppRole secret-zero that bootstraps that path is not kept in a keychain — the runtime secret injector publishes it into the agent’s ambient environment (doppler run). The keychain stays what its name says: login-convenience automated reads and human-only break-glass material. See the four-tier model.
No GitHub token lives here. Every GitHub token is an ephemeral GitHub App installation token minted on demand and never written to disk. See GitHub access for the model.

Two databases, one rule

The split is the entire access-control model: anything an AI can read non-interactively lives in automation; anything that requires a human at the keyboard lives in elevate-access. Machine secret-zero no longer lives on the keychain. The per-domain OpenBao AppRole that bootstraps T2 reaches an agent through the runtime secret injector’s ambient environment (doppler run), so the keychain holds only login-convenience and human-only material — never the AppRole, and never application secrets.

Reading a keychain entry the right way

The last positional argument is the keychain path. Omit it and security searches the login keychain only — which does not contain these entries. Always pass the path explicitly so the lookup hits the right database:
For human-only entries, point at the separate elevate-access-tier keychain instead. Each security find-generic-password call against a locked keychain triggers an unlock prompt; inlining the read on every command would prompt every time. Fetch once, inject the variable across the session — and unset it when done.

Adding a new keychain entry

Point at the elevate-access-tier keychain instead for human-only entries. The -U flag updates if the entry already exists.

Best practices

  • Pick one account name for AI-readable entries and use it consistently. The -a flag is the discriminator.
  • Never put a value in automation that should require human approval. The unlock posture is the whole point.
  • Cap the auto-lock timeout on elevate-access (~5 minutes idle) so an abandoned session re-locks.
  • Touch ID for sudo (security.pam.enableSudoTouchIdAuth = true in nix-darwin) ensures even the human path requires biometric confirmation.
  • Prefer an engine-minted, expiring credential over a stored one. A static key belongs in a keychain only when no engine can mint it.

See also

  • GitHub access — the ephemeral installation-token model that replaced GitHub tokens in the keychain.
  • Local AI isolation — the scoping that pairs with the keychain split.
  • BWS — uses automation for its access token to remain AI-reachable.