Detect locked keychain and provide better auth error message

did:plc:b2mcbcamkwyznc5fkplwlxbf opened this Feb 11, 2026 0 comments
did:plc:b2mcbcamkwyznc5fkplwlxbf opened Feb 11, 2026

Context

When a Mac is locked (screen saver, sleep), the OS keychain may become temporarily inaccessible. @napi-rs/keyring's getPassword() returns undefined for a missing entry but throws for a platform failure (locked keychain, access denied).

Currently resumeSession() in api-client.ts catches all errors and calls clearCurrentSessionMetadata(). This incorrectly wipes stored credentials when the keychain is just temporarily locked, forcing the user to run tangled auth login again unnecessarily.

macOS keychain behaviour

  • CLI tools (unsigned) do not automatically get an unlock dialog (unlike GUI apps)
  • When the screen is locked, no interactive prompts are possible; on screen unlock the login keychain typically auto-unlocks
  • The macOS security CLI tool can unlock the keychain interactively: security unlock-keychain

Tasks

  • Export a KeychainAccessError class from src/lib/session.ts
  • Wrap getPassword() throws in loadSession() and getCurrentSessionMetadata() as KeychainAccessError (any throw is a platform error; missing entries return undefined, not an error)
  • In resumeSession() in api-client.ts: rethrow KeychainAccessError without clearing metadata; only clear metadata for other errors (invalid/stale session)
  • Add ensureAuthenticated(client) helper to src/utils/auth-helpers.ts that calls resumeSession(), on KeychainAccessError tries security unlock-keychain (macOS only, prompts on TTY), retries once, then falls back to a clear error message with manual instructions
  • Replace the 7 repeated auth check blocks in src/commands/issue.ts with await ensureAuthenticated(client)
  • Add tests for: KeychainAccessError is rethrown without clearing metadata; unlock and retry success; unlock failure falls back to error message

Notes

On macOS, execSync('security unlock-keychain', { stdio: 'inherit' }) passes the terminal TTY through so the user is prompted for their keychain password. This only works in an interactive terminal; SSH sessions or locked screens will fall through to the error message with instructions to run security unlock-keychain manually.

No activity yet.

cospan · schematic version control on atproto built on AT Protocol