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.Two databases, one rule
The split is the entire access-control model: anything an AI can read non-interactively lives inautomation; 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 andsecurity searches the login keychain only — which does not contain these entries. Always pass the path explicitly so the lookup hits the right database:
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
-U flag updates if the entry already exists.
Best practices
- Pick one account name for AI-readable entries and use it consistently. The
-aflag is the discriminator. - Never put a value in
automationthat 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 = truein 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
automationfor its access token to remain AI-reachable.