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
securityCLI tool can unlock the keychain interactively:security unlock-keychain
Tasks#
- Export a
KeychainAccessErrorclass fromsrc/lib/session.ts - Wrap
getPassword()throws inloadSession()andgetCurrentSessionMetadata()asKeychainAccessError(any throw is a platform error; missing entries returnundefined, not an error) - In
resumeSession()inapi-client.ts: rethrowKeychainAccessErrorwithout clearing metadata; only clear metadata for other errors (invalid/stale session) - Add
ensureAuthenticated(client)helper tosrc/utils/auth-helpers.tsthat callsresumeSession(), onKeychainAccessErrortriessecurity 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.tswithawait ensureAuthenticated(client) - Add tests for:
KeychainAccessErroris 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.
Close by PR:
https://tangled.org/markbennett.ca/tangled-cli/pulls/3